Redis过期策略与淘汰策略

时间:2021-11-30
本文章向大家介绍Redis过期策略与淘汰策略,主要包括Redis过期策略与淘汰策略使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

参加面试连过期策略和淘汰策略概念都傻傻分不清楚

参加了一个面试,面试官问我过期策略有几种,我TM给人说了几种淘汰策略,面试官一脸无辜,我还感觉良好

开始正文吧:

1、过期策略(过期键的删除策略):redis使用过程中,很多时候我们会设置一个过期时间,那么当时间到了的时候,数据会立马删除吗?有可能会,也有可能不会,这就跟过期策略有关了,就是看看redis是如何知道过期的,并且进行的删除。

  先说结论:有三种

  第一种:定时删除

    在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。

    优点:对内存最友好的。可以及时释放键所占用的内存。

    缺点:对 CPU 不友好。特别在过期键比较多的情况下,删除过期键会占用相当一部分 CPU 时间。同时在内存不紧张,CPU 紧张的情况下,将 CPU 用在删除和当前任务不想关的过期键上,

    无疑会对服务器响应时间和吞吐量造成影响。

   第二种:惰性删除

    放任键过期不管,但是每次从键空间中读写键时,都会检查取得的键是否过期。如果过期就删除该删,否则就返回该键。(PS:键空间是一个保存了数据库所有键值对的数据结构)

    优点:对 CPU 最友好。只有在操作的时候进行过期检查,删除的目标仅限于当前需要处理的键,不会在删除其他无关本次操作的过期键上花费任何 CPU 时间。

    缺点:对内存不友好。这个十分容易理解了,键过期了,但因为一直没有被访问到,所以一直保留着(除非手动执行 flushdb 操来于清空当前数据库中的所有 key。),相当于内存泄漏。

   第三种:定期删除

    每隔一段时间,程序就对数据库进行检查,删除里面的过期键。至于要删除多少过期键,以及检查多少数据库,则有算法决定。该策略是上述两种策略的折中方案,需要通过实际情况,

    来设置删除操作的执行时长和频率。明白了过期键的删除策略后,那 redis 服务器又是采用什么策略来删除过期键的呢?实际上,Redis 服务器使用的是惰性删除和定期删除两种策略,

    通过配合使用,服务器可以很好的平衡 CPU 和内存。其中惰性删除为 redis 服务器内置策略。而定期删除可以通过以下两种方式设置:

  1. 配置 redis.conf 的 hz 选项,默认为10 (即 1 秒执行 10 次,值越大说明刷新频率越快,对 Redis 性能损耗也越大)
  2. 配置 redis.conf 的 maxmemory 最大值,当已用内存超过 maxmemory 限定时,就会触发主动清理策略

2、淘汰策略:当redis使用内存超过配置最大内存时,如果再有数据插入缓存,改如何处理,这就涉及到数据的淘汰策略,和定期删除中第二点

     应该是相同的内容。其实我觉得定期删除中,不应该加入第二点内容,第二点和淘汰策略就是一回事,应该直接讲解淘汰策略就完事了。

  淘汰策略有8中:

    1. no eviction:当内存使用超过配置的时候会返回错误,不会驱逐任何键

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

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

    4. allkeys-random:加入键的时候如果过限,从所有key随机删除

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

    6. volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键

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

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

  对LRU做一个简单说明:

  

    1. 新增key value的时候首先在链表结尾添加Node节点,如果超过LRU设置的阈值就淘汰队头的节点并删除掉HashMap中对应的节点。

    2. 修改key对应的值的时候先修改对应的Node中的值,然后把Node节点移动队尾。

    3. 访问key对应的值的时候把访问的Node节点移动到队尾即可。

  Redis的LRU实现

    Redis维护了一个24位时钟,可以简单理解为当前系统的时间戳,每隔一定时间会更新这个时钟。每个key对象内部同样维护了一个24位的时钟,

    当新增key对象的时候会把系统的时钟赋值到这个内部对象时钟。比如我现在要进行LRU,那么首先拿到当前的全局时钟,

    然后再找到内部时钟与全局时钟距离时间最久的(差最大)进行淘汰,这里值得注意的是全局时钟只有24位,按秒为单位来表示才能存储194天,

    所以可能会出现key的时钟大于全局时钟的情况,如果这种情况出现那么就两个相加而不是相减来求最久的key。

参考:

https://segmentfault.com/a/1190000017776475

https://zhuanlan.zhihu.com/p/105587132

原文地址:https://www.cnblogs.com/zxg-blog/p/15624672.html