Redis面试题分享六:Redis 过期策略和内存淘汰策略?

一、Redis的过期策略

过期策略:定期删除 + 惰性删除

(1) 定期删除:redis默认每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果有过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载。

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

默认情况下 Redis 定期检查的频率是每秒扫描 10 次,用于定期清除过期键。当然此值还可以通过配置文件进行设置,在 redis.conf 中修改配置“hz”即可,默认的值为“hz 10”。

小贴士:定期删除的扫描并不是遍历所有的键值对,这样的话比较费时且太消耗系统资源。Redis 服务器采用的是随机抽取形式,每次从过期字典中,取出 20 个键进行过期检测,过期字典中存储的是所有设置了过期时间的键值对。如果这批随机检查的数据中有 25% 的比例过期,那么会再抽取 20 个随机键值进行检测和删除,并且会循环执行这个流程,直到抽取的这批数据中过期键值小于 25%,此次检测才算完成。

Redis 服务器为了保证过期删除策略不会导致线程卡死,会给过期扫描增加了最大执行时间为 25ms。

(2) 惰性删除:定期删除可能导致很多过期的key 到了时间并没有被删除掉。这时就要使用到惰性删除。在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且过期了,是的话就删除。

二、内存淘汰策略

在 Redis 4.0 版本之前有 6 种策略,4.0 增加了 2种,主要新增了LFU算法。

根据redis.conf的配置文件中,我们可以得出,主要分为如下六种淘汰机制。

  • # volatile-lru -> Evict using approximated LRU among the keys with an expire set.
  • # allkeys-lru -> Evict any key using approximated LRU.
  • # volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
  • # allkeys-lfu -> Evict any key using approximated LFU.
  • # volatile-random -> Remove a random key among the ones with an expire set.
  • # allkeys-random -> Remove a random key, any key.
  • # volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
  • # noeviction -> Don't evict anything, just return an error on write operations.


这六种机制主要是什么意思内,下面是分别针对上面的几种机制做一个说明。


volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。

allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)。

volatile-lfu:当内存不足以容纳新写入数据时,在过期密集的键中,使用LFU算法进行删除key。

allkeys-lfu:当内存不足以容纳新写入数据时,使用LFU算法移除所有的key。

volatile-random:当内存不足以容纳新写入数据时,在设置了过期的键中,随机删除一个key。

allkeys-random:当内存不足以容纳新写入数据时,随机删除一个或者多个key。

volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

noeviction(默认):当内存不足以容纳新写入数据时,新写入操作会报错。

其中,默认的淘汰策略是 noevition,也就是不淘汰;

我们可以对 8 种淘汰策略可以分为两大类:

不进行淘汰的策略

noevition,此策略不会对缓存的数据进行淘汰,当内存不够了就会报错,因此,如果真实数据集大小大于缓存容量,就不要使用此策略了。

会进行淘汰的策略
        在所有数据中筛选

                allkeys-random:随机删除
                allkeys-lru:使用 LRU 算法进行筛选删除
                allkeys-lfu:使用 LFU 算法进行筛选删除


        在设置了过期时间的数据中筛选

                volatile-random:随机删除
                volatile-ttl:根据过期时间先后进行删除,越早过期的越先被删除
                volatile-lru:使用 LRU 算法进行筛选删除
                volatile-lfu:使用 LFU 算法进行筛选删除

以 volatile 开头的策略只针对设置了过期时间的数据,即使缓存没有被写满,如果数据过期也会被删除。

以 allkeys 开头的策略是针对所有数据的,如果数据被选中了,即使过期时间没到,也会被删除。当然,如果它的过期时间到了但未被策略选中,同样会被删除。

LRU算法

LRU 全称是 Least Recently Used,即最近最少使用,会将最不常用的数据筛选出来,保留最近频繁使用的数据。

LRU会把所有数据组成一个链表,链表头部称为 MRU,代表最近最常使用的数据;尾部称为 LRU代表最近最不常使用的数据;

但是,如果直接在 Redis 中使用 LRU 算法也会有一些问题:

LRU 算法在实现过程中使用链表管理所有缓存的数据,这会给 Redis 带来额外的开销,而且,当有数据访问时就会有链表移动操作,进而降低 Redis 的性能。

于是,Redis 对 LRU 的实现进行了一些改变:

记录每个 key 最近一次被访问的时间戳(由键值对数据结构 RedisObject 中的 lru 字段记录)
在第一次淘汰数据时,会先随机选择 N 个数据作为一个候选集合,然后淘汰 lru 值最小的。(N 可以通过 config set maxmemory-samples 100 命令来配置)
后续再淘汰数据时,会挑选数据进入候选集合,进入集合的条件是:它的 lru 小于候选集合中最小的 lru。
如果候选集合中数据个数达到了 maxmemory-samples,Redis 就会将 lru 值小的数据淘汰出去。
------------------

LFU算法
LFU(Least Frequently Used)是根据数据的使用次数来进行缓存淘汰的,以此来保留常用的数据,同时淘汰不常使用的数据。

LFU 算法会维护一个使用次数列表,其中每个节点都是一个缓存对象。当对某个对象进行 get 操作时,该节点的使用次数会增加,因此需要更新节点在列表中的位置。当需要淘汰一个缓存对象时,LFU算法选择使用次数最少的缓存对象进行淘汰。

LFU算法的实现有两种方式:

一种是基于计数器的实现,即每次访问缓存对象时将计数器加一;


另一种是基于时间窗口的实现,即将每个缓存对象的访问时间存储下来,然后统计在一段时间窗口内访问次数最少的缓存对象进行淘汰。


LFU算法相对于LRU算法,能更好地反映缓存对象的使用次数和频率,因此在一些场景下,例如热点数据缓存、广告推荐系统等,LFU算法更能够提高缓存的命中率,并且可以更好地满足业务需求。但是,LFU算法的实现较为复杂,需要维护使用次数列表,并且计算复杂度较高。因此,需要根据具体业务场景来选择合适的缓存淘汰算法。

--------------------

为什么 Redis 有了 LRU 还需要 LFU
虽然 LRU 算法在大多数应用场景下都可以提供良好的缓存效果,但有一些场景下 LRU 算法的效果可能不太好,这时就需要使用 LFU 算法。

LRU 算法假设最近使用过的数据是有可能在近期再次使用的,因此最近被访问的数据不会被淘汰。然而,对于那些虽然使用频率很小,但是其访问之间的时间跨度很长,依然会在链表的头部,一直没有被淘汰,降低了整个缓存的效率。这种缓存中一些生命周期比较长但访问频次比较低的数据叫做“历史遗留数据”,LFU算法就是为了更好地处理这些数据。

LFU 算法会把访问次数最少的数据从缓存中淘汰,因此更适用于那些依赖访问频次而不是访问时间的数据场景,例如一些热门商品的热度排行榜,如果以 LRU 算法进行缓存,那么当热点商品长时间没有被访问时,就会被淘汰掉,使得热度排行榜的效果大打折扣。而LFU算法能够根据热度排行榜中的商品访问频次来淘汰数据,更能够体现数据的热度,使得缓存效果更加精确。

综上所述,LRU算法和LFU算法各有优缺点,可以根据具体的业务场景来选择实现缓存逻辑。而Redis既支持LRU算法,也支持LFU算法,因此它可以根据不同的业务场景选择不同的算法实现,以提供更加高效、精准的缓存服务。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值