是什么?
Redis 是当前最受欢迎的非关系型数据库之一。它是使用 C 语言编写的开源项目,支持多种数据类型、支持网络、基于内存、可选持久性的 Key-Value 数据库。它提供多种语言的 API 支持,应用十分广泛。
Redis 的优点
快。非常快。Redis 使用C语言编写,它基于内存采用单线程,据官方提供的数字来说可达 10w QPS。
1. 完全基于内存,大部分的存取操作都是纯内存操作,它的数据储存在 hashmap 中,查找和操作的时间复杂度都是 O(1).
2. 它是单线程,这避免了上下文的切换以及竞态条件,避免了加锁释放锁等造成的损耗。虽然是单线程但是它采用了多路复用io机制来支持并发。
3. Redis实现了自己的VM机制。了解Redis的VM机制请进:https://blog.youkuaiyun.com/weixin_43618070/article/details/83894031
支持的数据类型
- 字符串 String
- 列表 List
- 哈希表 Hash
- 集合 Set
- 有序集合 ZSet
redis其他特点
持久化
存储结构
redis的四种架构介绍
其他问题
什么是一致性哈希
Redis是基于CAP理论的,什么是CAP理论
常用实现Redis分布式锁
Redis做异步队列
做缓存、缓存穿透、缓存雪崩
Redis如何淘汰过期的 keys
我们知道 Redis 可以为 keys 设置过期时间。所以对于过期的 keys 需要一个淘汰机制进行删除。
Redis keys过期有两种方式:被动和主动方式。
当一些客户端尝试访问它时,key会被发现并主动的过期。
当然,这样是不够的,因为有些过期的keys,永远不会访问他们。 无论如何,这些keys应该过期,所以定时随机测试设置keys的过期时间。所有这些过期的keys将会从密钥空间删除。
1、具体就是Redis每秒10次做的事情:
2、测试随机的20个keys进行相关过期检测。
3、删除所有已经过期的keys。
如果有多于25%的keys过期,重复步奏1.
这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的keys的百分百低于25%,这意味着,在任何给定的时刻,最多会清除1/4的过期keys。
回收策略
当内存撑满,让Redis自动回收旧数据是件很方便的事情,LRU是Redis唯一支持的回收方法。
当maxmemory限制达到的时候Redis会使用的行为由 Redis的maxmemory-policy配置指令来进行配置。
以下的策略是可用的:
- noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)
- allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
- volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
- allkeys-random: 回收随机的键使得新添加的数据有空间存放。
- volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
- volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
如果没有键满足回收的前提条件的话,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了。
选择正确的回收策略是非常重要的,这取决于你的应用的访问模式,不过你可以在运行时进行相关的策略调整,并且监控缓存命中率和没命中的次数,通过RedisINFO命令输出以便调优。
一般的经验规则:
- 使用allkeys-lru策略:当你希望你的请求符合一个幂定律分布,也就是说,你希望部分的子集元素将比其它其它元素被访问的更多。如果你不确定选择什么,这是个很好的选择。.
- 使用allkeys-random:如果你是循环访问,所有的键被连续的扫描,或者你希望请求分布正常(所有元素被访问的概率都差不多)。
- 使用volatile-ttl:如果你想要通过创建缓存对象时设置TTL值,来决定哪些对象应该被过期。
allkeys-lru 和 volatile-random策略对于当你想要单一的实例实现缓存及持久化一些键时很有用。不过一般运行两个实例是解决这个问题的更好方法。
为了键设置过期时间也是需要消耗内存的,所以使用allkeys-lru这种策略更加高效,因为没有必要为键取设置过期时间当内存有压力时。
对LRU原理感兴趣的同学可以阅读这篇文章:https://blog.youkuaiyun.com/hopeztm/article/details/79547052
简单动态字符串 SDS (Simple Dynamic String)
这是 Redis 自己构建的一个基本的数据类型,结构如下:
struct sdshdr {
int len;
int free;
char buf[];
}
SDS几乎贯穿了Redis的所有数据结构,应用十分广泛。
1、通过使用 SDS 而不是 C 字符串, Redis 将获取字符串长度所需的复杂度从 O(N) 降低到了 O(1) , 这确保了获取字符串长度的工作不会成为 Redis 的性能瓶颈。
2、SDS 的空间分配策略完全杜绝了发生缓冲区溢出的可能性。当 SDS API 需要对 SDS 进行修改时, API 会先检查 SDS 的空间是否满足修改所需的要求, 如果不满足的话, API 会自动将 SDS 的空间扩展至执行修改所需的大小, 然后才执行实际的修改操作, 所以使用 SDS 既不需要手动修改 SDS 的空间大小, 也不会出现前面所说的缓冲区溢出问题。
3、减少修改字符串时带来的内存重分配次数
参考:http://redisbook.com/preview/sds/different_between_sds_and_c_string.html
常用命令