Redis的过期和淘汰是两回事儿
早期文章
做程序员的竞争越来越大,有一种三百六十行,行行转程序员的感觉。当程序员的想着转行做送外卖逃离 007、996,送外卖的却想着转行当程序员。看到群里小伙伴发的照片,想起以前一个阿姨在地铁上学 Java Web 的照片,真的是太卷了……不,是太励志了!
今天整理一下关于 Redis 的过期策略和淘汰机制,这两个东西看着很像,其实不是一回事儿。
过期策略
我们在使用 Redis 当作缓存时,通常会给 Redis 的 Key 设置一个过期时间,被设置过期时间的 Key 在未过期时可以对其进行读取或更新操作,也可以主动将其删除。当其超过设置的时间后,它将失效。通过它的过期机制,可以完成很多功能,比如计数器复位、token 过期等。
那么,Redis 对已经过期的数据是进行如何处理,或者说是如何删除呢?在 Redis 中有两种策略来删除过期的 Key,分别是 主动删除和 被动删除 两种方式,也有资料称为 定期删除 和 惰性删除。
被动删除(惰性删除)
被动删除也被称为惰性删除,是 Redis 中的 Key 已经过期,但是 Redis 不会主动将其删除,当有客户端访问该过期 Key 时,Redis 对其进行检查,发现其过期则将其删除,并返回 null 给客户端。
主动删除(定期删除)
惰性删除有它的优点,不会浪费太多的系统资源,但是也存在相应的问题,就是已经过期的 Key 如果不再被访问,就不会被删除了,这样会浪费不必要的存储空间。因此 Redis 存在一种主动删除过期 Key 的策略。
主动删除也被称为定期删除,Redis 会定期扫描已经设置了过期时间的 Key,然后从中删除已经过期的 Key。Redis 默认一秒钟完成 10 次这样的扫描,它大概的流程如下:
从设定了过期的 Key 中随机抽取 20 个 Key 进行过期检测
删除所有已经过期的 Key
如果有本次删除的 Key 超过 25%,那么重复第一步
如果有大量的 Key 过期,这样的扫描可能会导致线程卡顿,因此每次扫描的时长最长为 25ms。
以上是 Redis 处理过期 Key 的方案,当 Redis 服务器占用的内存空间超过最大允许内存之后,会触发内存的淘汰策略。
淘汰策略
内存淘汰策略是指 Redis 使用的内存达到或超过其配置的最大内存时触发的一种保护策略,它根据具体的策略来淘汰一些 Key 使得 Redis 可以继续运行。在 Redis 4.0 之后的版本中,Redis 的内存淘汰策略共有 8 种。
noeviction:内存达到配置的最大内存时,不再接受新增 Key 的操作,它是默认配置
allkeys-lru:在所有 Key 中,保留最近使用的 Key,删除最近最少使用的 Key
allkeys-lfu:在所有 Key 中,保留常用的 Key,删除最不常用的 Key
allkeys-random:在所有 Key 中,随机删除一些 Key
volatile-lru:在设置了过期时间的 Key 中,删除最近最少使用的 Key
volatile-lfu:在设置了过期时间的 Key 中,删除最不常用的 Key
volatile-random:在设置了过期时间的 Key 中,随机删除一些 Key
volatile-ttl:在设置了过期时间的 Key 中,删除最短剩余生存时间中最不常用的 Key
从上面的策略中可以看出,大体分为两类,分别是 allkeys 和 volatile 两种。allkeys 是所有的 Key,volatile 是设置了过期时间的 Key。在 allkeys 和 volatile 中使用两个淘汰策略是 LRU 和 LFU,即 最近最少使用(确切的是 近似 LRU 算法) 和 最不常用 两种。
小结
过期和淘汰是两回事,过期是对设置过期时间的 Key 进行删除的一种机制,而淘汰是当使用内存超过设置最大内存时触发的一种保护机制,虽然它也会删除一些 Key。上面整理的是关于 Redis 的过期和淘汰的知识点,具体应该怎么设置淘汰策略,官网给出了建议。需要了解 LRU 和 LFU 算法也可以在官网得到具体的说明。
公众号内回复 【mongo】 下载 SpringBoot 整合操作 MongoDB 的文档。
公众号内回复 【cisp知识整理】 下载 CISP 读书笔记。
公众号内回复【java开发手册】获取《Java开发手册》黄山版。