Redis - 数据过期删除策略

Redis 中提供了三种过期删除的策略:

分类

1、被动删除:惰性删除

2、主动删除

1)定时删除

2)定期删除

3)当前已用内存超过maxmemory限定时,触发内存淘汰策略(主动清理)

含义

1)定时删除
在设置某个 key 的过期时间,同时创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。

实现原理:过期键的定期删除策略由redis.c/activeExpireCycle函数实现,每当Redis的服务器周期性操作redis.c/serverCron函数执行时,activeExpireCycle函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。

优点:通过使用定时器,可以保证过期 key 可以被尽快的删除,并且释放过期 key 所占用的内存

缺点:对 CPU 是不友好的,当过期键比较多的时候,删除过期 key 会占用相当一部分的 CPU 资源,对服务器的响应时间和吞吐量造成影响。

2)定期删除

每隔一段时间随机抽取一些(由算法决定,不可能全部key,比如检查10w 个 key,那 redis 基本上就崩了,cpu 负载会很高)设置了过期时间的 key,检查其是否过期,如果过期就删除(配置redis.conf的hz选项,默认为10,1s刷新的频率。即1秒执行10次,相当于100ms执行一次,hz值越大,说明刷新频率越快,Redis性能损耗也越大)

定期删除是对上面两种删除策略的一种整合和折中,其难点是确定删除操作执行的时长和频率:

  • 如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过多地消耗在删除过期键上
  • 如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况

每个一段时间就对一些 key 进行采样检查,检查是否过期,如果过期就进行删除

1、采样一定个数的key,采样的个数可以进行配置,并将其中过期的 key 全部删除;

2、如果过期 key 的占比超过可接受的过期 key 的百分比,则重复删除的过程,直到过期key的比例降至可接受的过期 key 的百分比以下。

优点:定期删除,通过控制定期删除执行的时长和频率,可以减少删除操作对 CPU 的影响,同时也能较少因过期键带来的内存的浪费。

缺点:

a、执行的频率不太好控制

b、频率过快对 CPU 不友好,如果过慢了就会对内存不太友好,过期的键值对不能及时的被删除掉

c、如果一个键值对过期了,但是没有被删除,这时业务再次获取到这个键值对,那就会获取到被删除的数据了,这肯定是不合理的

定期删除可能会导致很多过期 key 到了时间并没有被删除掉,此时就需要惰性删除。

3)惰性删除
惰性删除,当一个键值对过期时,只有再次用到这个键值对的时候才去检查删除这个键值对,也就是如果用不着,这个键值对就会一直存在。

实现原理:过期键的惰性删除策略由db.c/expireIfNeeded函数实现,所有读写数据库的Redis命令在执行之前都会调用expireIfNeeded函数对输入键进行检查。如果输入键已经过期,那么expireIfNeeded函数将输入键从数据库中删除;如果输入键未过期,那么expireIfNeeded函数不做动作。

优点:对 CPU 是友好的,只有在取出键值对的时候才会进行过期检查,这样就不会把 CPU 资源花费在其他无关紧要的键值对的过期删除上。

缺点:如果一些键值对永远不会被再次用到,那么将不会被删除,最终会造成内存泄漏,无用的垃圾数据占用了大量的资源,但服务器却不能去删除。

 

总结:上面讨论的三种策略,都有或多或少的问题。Redis 中实际采用的策略是定期删除+惰性删除的组合方式:定期删除,获取 CPU和内存的使用平衡,针对过期的key可能得不到及时的删除;当key被再次获取的时候,通过惰性删除再做一次过期检查,来避免业务获取到过期内容。

为什么不用定时删除策略

定时删除用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是非常消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此Redis实际中没有采用这一策略。

现在还面临一个问题:如果定期删除漏掉了很多过期的key,此时也没有及时去查(即未走惰性删除),此时怎么样?如果大量过期的key堆积在内存里,可能导致redis内存块即将耗尽(OOM),应该怎么做?

解决方案:会执行内存淘汰策略

Redis持久化时,过期键的处理策略
1)AOF

• AOF写⼊阶段:该值还没有被删除,保留过期键;真正删除时候追加⼀条DEL命令

• AOF重写阶段:已过期的键不会被保存到重写后的AOF⽂件中

2)RDB

• RDB⽣成阶段:对key进⾏检查,过期的key不会被载⼊到数据库中

• RDB加载阶段:

◦ 主服务器:载⼊时候,会对key进⾏检查,过期时候不会被加载到数据库中

◦ 从服务器:⽆论是否过期都会被载⼊(主从服务器同步时候,从服务器数据会被清空,所以过期键写到从服务器影响不大)

Redis主从模式中,过期键的处理策略

▪ 从库对过期键删除是被动的(从库读到过期键还是会返回),等主库key到期时,在AOF中追加⼀条DEL命令,同步到所有从库

posted @ 2024-02-28 23:07  李若盛开  阅读(1348)  评论(0)    收藏  举报