目录
- 一、过期删除策略
- 1、定时删除策略
- 2、惰性删除策略
- 二、内存淘汰机制
一、过期删除策略
Redis
所有的数据结构都可以设置过期时间,时间一到,就会自动删除。
那么如何进行过期删除的呢?有两种策略:
-
定时删除策略(主动检测)
; -
惰性删除策略(被动检测)
;
Redis
是将每个设置了过期时间的 key
放入到一个独立的字典中,以后会定时遍历这个字典来删除到期的 key 。除了定时遍历之外,它还会使用惰性策略来删除过期的key,所谓惰性策略就是在客户端访问这个key的时候,Redis 对 key 的过期时间进行检查,如果过期了就立刻删除。
定时删除是集中处理
,惰性删除是零散处理
。
1、定时删除策略
Redis默认会每秒进行十次过期扫描
,过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。
步骤如下:
从过期字典中随机 20 个 key 进行过期检测
;删除这 20 个 key 中已经过期的 key
;如果过期的 key 比率超过 1/4 ,那就重复步骤 1
;
设想一个大型的 Redis 实例中所有的 key 在同一时间过期,会出现怎样的结果?
毫无疑问,Redis 会持续扫描过期字典(循环多次),直到过期字典中过期的 key 变的稀疏,才会停止(循环次数明显下降),这就会导致线上读写请求出现明显的卡顿现象
。导致这种卡顿的另外一种原因是内存管理器需要频繁的回收内存页,这也会产生一定的 CPU 消耗
。
所以业务开发人员一定要注意过期时间,如果有大批量的 key 过期,要给过期时间设置一个随机范围,而不能全部在同一时间过期
。
从库过期策略
从库不会进行过期扫描,从库对过期的处理是被动的
,主库在 key 到期时,会在 AOF
文件里增加一条 del
指令,同步到所有的从库,从库通过执行这条 del 指令来删除过期的 key
。
因为指令同步是异步进行的
,所以主库过期的 key
的 del
指令没有及时同步到从库的话,会出现主从数据的不一致
,主库没有的数据在从库里还存在。
定期删除可能会导致很多过期key到了时间并没有被删除掉,所以就有了惰性删除
。
假如你的过期key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个key,才会被Redis给删除掉,这就是所谓的惰性删除,即当你主动去查过期的key时,如果发现key过期了,就立即进行删除,不返回任何数据。
总结:定期删除是集中处理,惰性删除是零散处理
。
2、惰性删除策略
所谓的惰性策略就是在客户端访问这个key的时候,Redis对key的过期时间进行检查,如果过期了就立刻删除,不会给你返回任何数据。
二、内存淘汰机制
当Redis内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换(swap),交换会让Redis的性能急剧下降
,对于访问量比较频繁的Redis来说,这样龟速的存取效率基本上等于不可用。
在生产环境中我们是不允许Redis出现交换行为的,为了限制最大使用内存,Redis提供了配置参数 maxmemory
来限制内存超出期望。
当实际内存超出 maxmemory
时,为了让用户自己决定该如何腾出新的空间以继续提供读写服务,Redis提供了几种可选策略(maxmemory-policy):
策略 | 说明 |
---|---|
noeviction | 不继续提供写服务,读请求以及 del 请求可以继续服务,这样可以保证不会丢失数据,但是会让线上的业务不能持续进行,这是默认的淘汰策略。 |
volatile-lru | 尝试淘汰设置了过期时间的key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。 |
volatile-ttl | 跟上面一样,除了淘汰的策略不是LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。 |
volatile-random | 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。 |
allkeys-lru | 区别于volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合,这意味着没有设置过期时间的 key 也会被淘汰。 |
allkeys-random | 跟上面一样,不过淘汰的策略是随机的key。 |
总结:
-
volatile-xxx
:策略只会针对带过期时间的key进行淘汰; -
allkeys-xxx
:策略会对所有的 key 进行淘汰。
如果你只是拿Redis做缓存
,那应该使用 allkeys-xxx
,客户端写缓存时不必携带过期时间,如果你还想同时使用Redis的持久化功能
,那就使用 volatile-xxx
策略,这样可以保留没有设置过期时间的 key,他们是永久的 key
不会被 LRU算法
淘汰。