Redis 淘汰策略

Redis已经设置了过期时间也就是TTL,那么键过期了不就是已经删除了吗?为什么还存在淘汰策略呢?

这要从Redis的过期策略来聊起

过期策略分为两种

  • 一个是定时删除
  • 还有一个是惰性删除

先来看下定时删除,就是Redis会将每个设置了过期时间的key,放入到一个独立的字典中,然后会定期遍历这个字典来删除到期的key。除了定时遍历之外,它还会使用惰性策略来删除过期的 key。

所谓惰性策略就是在客户端访问这个 key 的时候,Redis 对 key 的过期时间进行检查,如果过期了就立即删除。

说白了,定时删除是集中处理,而惰性删除是零散处理。

因为Redis不可能遍历这个字典中所有的key

举个例子:假如 Redis 中存了几十万个 key,每隔一段时间就会遍历所有的设置过期时间的Key,就会给CPU带来很大的负载。

所以Redis默认会每秒进行十次过期扫描,也就是100MS一次,过期扫描不会遍历过期字典中所有的Key,而是采用了一种简单的贪心策略

什么是贪心策略

  • 就是从过期字典中随机20个key
  • 删除这 20 个 key 中已经过期的 key;
  • 如果过期的 key 比率超过 1/4,那就重复步骤 1;

同时,为了保证过期扫描不会出现循环过度,导致线程卡死现象,算法还增加了扫描时间的上限,默认不会超过 25ms。

如何配置定期删除执行的时间间隔呢?

Redis的定时任务默认是1s执行10次,也就是100ms一次,值越大说明刷新频率越快,对Redis性能损耗也越大,如果要修改这个值,可以在redis.conf中修改hz的值。

在这里插入图片描述
可以看到在 redis.conf 这个文件中,默认为10,提高它的值将会占用更多的cpu,当然,相应的Redis将会更快的处理,同时到期的许多key,以及更精确的去处理超时。hz的取值范围是1~500,通常不建议超过100,只有在请求延时非常低的情况下可以将值提升到100。

介绍了过期策略,就知道为什么要使用淘汰策略了吧

淘汰策略

如果说定期删除漏掉了很多过期的 key,后期也没及时去查过期key,也就是没走惰性删除,此时大量过期key堆积在内存里,导致Redis内存块耗尽了,这时候就要使用 Redis 的内存淘汰机制解决这个问题,也就是当前已使用内存超过maxmemory限定时,触发内存淘汰机制

这个值是在 redis.conf 文件中设置的,如下图所示:

在这里插入图片描述

内存淘汰策略有这么几种

  • noeviction:当内存使用超过配置的时候会返回错误,但是不会驱逐任何键

  • allkeys-lru:加入键的时候,如果超过限制,首先通过LRU算法驱逐最久没有使用的键

  • volatile-lru:加入键的时候,如果超过限制,首先从设置了过期时间的键集合中驱逐最久没有使用的键

  • allkeys-random:加入键的时候如果过限,从所有key随机删除。我们的应用对于缓存key的访问概率相等,则可以使用这个策略。

  • volatile-random:加入键的时候如果过限,从过期键的集合中随机驱逐

  • volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键。这种策略使得我们可以向Redis提示哪些key更适合被驱逐

  • volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键

  • allkeys-lfu:从所有键中驱逐使用频率最少的键

这就是内存淘汰策略的几种模式在Redis中的用途

接下来看下LRULFU的实现方式

先来看下LRU的实现方式

在这里插入图片描述

  • 新数据插入到链表头部;
  • 每当缓存命中(也就是缓存数据被访问)的时候,就会将数据移动到链表头部
  • 当链表满的时候呢,将链表尾部的数据丢弃

简单来说就是淘汰长时间没有被使用的键,以时间作为参考

我们再来看下LFU他的实现方式是什么样的

在这里插入图片描述

  • 新加入数据插入到队列尾部
  • 队列中的数据被访问后,引用次数增加,队列重新排序
  • 当需要淘汰数据时,将已经排序的列表最后的数据块删除

简单来说就是淘汰一定时间内被访问次数最少的键,以次数作为参考

这就是有关于淘汰策略

了解更多可扫码关注公众号
在这里插入图片描述

posted on 2021-12-15 19:39  凝神遐想  阅读(92)  评论(0编辑  收藏  举报

导航