Redis的数据已经设置了TTL,不是过期就已经删除了吗?为什么还存在所谓的淘汰策略呢?这个原因我们需要从redis的过期策略聊起。
一、Redis 过期键策略
redis键的过期时间都保存在过期字典中,过期键的删除策略有3种:
- 定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即删除对键的删除操作。
- 惰性删除:放任键过期不管,但每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键。如果没有过期,就返回该键。
- 定期删除:每隔一段时间,程序对数据库进行一次检查,删除里面的过期键。至于删除多少过期键,以及检查多少数据库,有算法决定。
1、定时删除特点
优点:对内存友好,通过定时器可以保证过期键过期键会尽可能快的删除,并释放过期键占用的空间。
缺点:1)cpu不友好,在过期键比较多的情况下,删除过期键可能会占用相当一部分cpu时间;在内存不紧张cpu紧张的情况下,将cpu时间用在删除和当前任务无关的过期键上,无疑会对服务器响应时间和吞吐量造成影响。2)创建定时器需要Redis服务器中的时间事件,而现在时间事件的实现方式是无序链表,查找一个事件的时间复杂度为O(N),并不能高效的处理大量时间事件。
2、惰性删除
优点:1)对cpu友好,程序只在取出键时才对建进行过期检查,删除的目标仅限于当前处理的键。
缺点:1)对内存不友好,当数据库中有大量的过期键,而这些键又没有被访问到,那么他们也许会永远不会被删除。
3、定期删除
定期删除是前两种删除策略的一种折中。会每隔一段时间执行一次删除过期键操作,并通过限制操作执行的时长和频率来减少删除操作对cpu时间的影响。
定期删除策略的难点是确定删除操作执行的时长和频率:
- 如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时删除策略,以至于将CPU时间过多地消耗在删除过期键上面
- 如果删除操作执行得太少,或者执行的时间太短,定期删除策略又会和惰性删除策略一样,出现浪费内存的情况
二、Redis内存淘汰策略
Redis内存淘汰策略
有了以上过期策略的说明后,就很容易理解为什么需要淘汰策略了,因为不管是定期采样删除还是惰性删除都不是一种完全精准的删除,就还是会存在key没有被删除掉的场景,如果大量过期key堆积在内存里,导致redis内存块耗尽了,怎么办?所以就需要内存淘汰策略进行补充,内存淘汰策略就是当redis使用的内存到达了最大内存阈值之后移除键的一种策略。Redis有如下几种内存淘汰策略:
- volatile-lru:从所有设置了过期时间的key中,选择删除最近最少使用的key
- allkeys-lru:从所有的key中选择删除最近最少使用的key
- volatile-lfu:从所有设置了过期时间的key中,选择删除使用频率最低的key
- allkeys-lfu:从所有key中选择删除使用频率最低的key
- volatile-random:从所有设置了过期时间的key中,随机选择删除key
- allkeys-random:从所有key中随机选择删除key
- volatile-ttl:从设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰,ttl值越大越优先被淘汰。
- noeviction:当内存达到阈值的时候,新的写入操作报错
总结
Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据。