Redis篇——深入了解Redis数据过期清除策略和缓存淘汰策略,一篇文章超详细、超细节!

数据过期清除策略

一、学习前言(过期key过多,容易出现的问题)
Redis存储的所有数据结构都可以设置过期时间,时间一到,就会将其自动删除。你也可以想象成有一条专门删除过期key的线程这个时候可能就会存在问题,如果某一时间段,过期的key太多了。会不会导致线程处理不过来。因为我们的Redis是单线程的,删除操作如果过于复杂,也会占用线程过多的时间,这样很大的可能会导客户端读写数据出现卡顿的现象!

二、常见数据过期清除策略
1、立即删除
它会在设置键的过期时间同时,创建一个定时器。当键到了过期的时间,定时器会立即对键进行删除。该策略能过够保证过期键尽快的删除,快速释放内存空间。
(1)优缺点
①优点
立即删除能保证内存中数据的最大新鲜度,因为保证了过期键值会在过期后被立即删除,其所占用的内存空间也会立即被释放。对内存来说是十分友好的。
②缺点
立即删除对CPU是不友好的。因为删除是会占用CPU时间的,如果刚好碰上了CPU处理事务比较繁忙,比如正在做交集或排序等计算的时候,就会给CPU造成额外的压力。
(2)总结
立即删除策略是对CPU不友好,但是对内存是很友好的,实际性质是用处理器性能换取内存空间!

2、惰性删除
数据达到过期时间,不做处理。等待下次访问该数据时,如果数据还未过期,返回数据;发现数据已过期,直接删除,返回不存在。

(1)开启惰性删除方法

lazyfree-lazy-eviction==yes #在redis.conf配置文件中找到这个配置,给它置成yes即可

(2)优缺点
①优点
对于CPU来说那是相当的友好了,减少了CPU资源的占有
②缺点
如果一个键过期了,如果这个键不经常被查询,那么这个键就会一直保留在Redis中,只要这个键过期而不被删除,那么他就会一直留在内存中而不被释放。因此对内存是非常不友好的。

(3)总结
在使用惰性策略时,如果你的数据库中有相当多的过期键,而这些键又恰好不被查询,那么她也就永远不会被删除(除非用户直接FLUSHDB或者FLUSHALL)。这种情况类似于内存泄漏——大量无用的数据占据了大量的内存,并且长期不被处理,服务器不会自己释放他们。这种情况对于非常依赖Redis的内存的服务器来说,肯定不是一个好消息。

3、定期删除
定期删除策略是立即删除策略和惰性删除策略的折中。就是兼顾了内存和CPU性能。
简单讲就是每隔一段时间执行一次删除过期key的操作,并限制删除操作执行时常和频率来减少删除操作对CPU的性能影响
Redis会将每个设置了过期时间的key放入到一个独立的字典中,以后会定时遍历这个字典来删除掉过期的key。除了定时遍历之外,还会使用惰性删除策略来删除过期的key。定期删除是集中处理,而惰性删除是零散处理。

(1)定时删除中的定时扫描策略
Redis默认会每秒进行10次过期键扫描,过期扫描并不会遍历过期字典中的所有的key,而是采用了一种贪心策略。
(1)从过期字典中随机20个key;
(2)删除这20个key中已经过期的key;
(3)如果过期的key比例超过了1/4(程序认为现在的过期key比较多),那就重复步骤(1);
于此同时,为了保证过期扫描不会出现循环过度,导致卡死线程现象,算法还增加了扫描时间上限,默认不会超过25ms。

但是上面这种定时扫描策略还是会带来另一个问题:
设想一个大型的Redis实例中的所有key在同一时间集中过期。Redis会持续的扫描过期字典(循环多次),直到过期字典中过期的key变的稀疏才会停止(循环次数明显下降)。这就导致线上读写请求出现明显的卡顿。导致卡顿的原因是内存管理器需要频繁回收内存页,这也会产生一定的CPU消耗!
即使算法还是增加了扫描时间上上限,也还是会出现卡顿的现象。假如有101个客户端同时将请求发送过来,然后前100个请求的时间都是25ms,那么第101个请求要等待多长时间呢???答案是2500ms(由于Redis是单线程的奥!),这个就是看客户端的卡顿时间,是由于服务器不间断的小卡顿积少成多导致的(此种情况是假设每一次扫描都达到了上限的25ms)
总结:因此,在实际的开发中需要特别的注意,避免大量key在同一时间过期。解决方案可以是给key在他本身的固定的过期时间上加上一个随即范围的时间!

(2)定期删除注意事项
①如果删除操作执行次数过多、执行时间太长,就会导致和定时删除同样的问题:占用大量CPU资源去进行删除操作
②如果删除操作次数太少、执行时间短,就会导致和惰性删除一样的问题:类似内存泄露!
所以,定期删除最关键的地方就是在于执行时常和频率的设置,将来在实际开发中依照需求,可在Redis的配置文件中配置!

缓存淘汰策略

一、了解缓存淘汰策略
1、当Redis内存超出了物理内存限制时,内存数据会开始和磁盘产生频繁的交换,交换会使Redis的性能急剧下降,对于访问比较频繁的Redis来说,这样的龟速的存取速率基本上等同于不可用。
2、一般在生产环境中,Redis内存会设置一个内存上限(maxmemory),如果有许多没有加过期时间的key,长期下来就会把Redis内存打满,出现OOM的异常。
3、定期删除时使用简单的贪心算法,这样肯定会出现一些没有没抽查到的数据。而惰性删除也会出现一些长时间没有被查询的key,这就会导致大量过期的key堆积在内存中,导致Redis内存空间紧张或者很难看快被耗尽。所以必须要有一个兜底的方案,那么这个方案就是缓存淘汰策略。

二、常见的缓存淘汰策略

1、noevction:不会继续服务写请求(DEL删除请求还可以继续服务),读请求可以继续进行。这样可以保证至少不会丢数据,但是会让线上的业务不能继续进行,这是默认的淘汰策略。

2、volatile-lru:尝试淘汰设置了过期时间的key,最近最长时间不使用的key优先被淘汰。没有设置过期时间的key,则不会被淘汰。这样可以保证需要持久化的数据不会突然丢失。

3、allkeys-lru:区别于volatile-lru,这个策略要淘汰的key对象是全体的key集合,而不只是设置了过期时间的key集合。这意味着没有设置过期时间的key也会被淘汰。

4、volatile-ttl:该策略是删除了设置过期时间并且即将过期的key。和volatile-lru相比,除了淘汰策略不是LRU,根据key的剩余寿命TTL的值,TTL值越小优先被淘汰。

5、volatile-random:对设置了过期时间的key随机淘汰。

6、allkeys-random:对所有的key随机淘汰。

7、volatile-lfu:对设置了过期时间的key,使用LFU算法进行淘汰。

8、allkeys-lfu:对所有的key集合,使用LFU算法进行淘汰。
总结:volatile-xxx是只针对设置了过期时间的key进行淘汰,allkeys-xxx策略时会对所有的key进行淘汰。如果你直拿Redis做缓存,那么 你应该去使用allkeys-xxx策略,客户端写缓存时就不必须携带缓存失效时间了。如果你想同时使用Redis的持久化功能,那就使用volatile-xxx策略,这样可以保留没有设置过期时间的key,他们是永久的key,不会被LRU和LFU算法淘汰!

至此,你已经掌握了Redis的数据过期清除策略和缓存淘汰策略的底层工作原理了,在实际开发中,如果你的项目中使用了Redis,是一定要考虑大量缓存如果过期怎么处理的情况,还需要考虑如果大量的永久key打满了内存要怎么处理,所以学好这篇文章中的策略至关重要!

后续还会持续更新相关技术栈,敬请期待~

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Be explorer

若认可笔者文章,手头富裕望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值