一、概述
redis缓存是在内存中保存数据,避免业务从数据库中读取数据,从而提升系统的响应速度,而redis缓存淘汰是指当缓存数据达到一定容量时,为了给新的数据腾出空间,需要按照一定的策略从缓存中移除旧的数据。
二、redis缓存淘汰策略。
1.noeviction:这种方式是不进行淘汰的,当内存不足以容纳新写入数据时,新写入操作会报错。
2.allkeys-lru: 当内存不足以容纳新写入数据时,它会从所有键值对中移除最近最少使用的键。
3.allkeys-lfu:lfu是在Redis 4.0 时引入,当内存不足以容纳新写入数据时,它会从所有键值对中移除最近使用频率最小的键。
4.allkeys-randoms:当内存不足以容纳新写入数据时,从所有键值对选择并随机移除。
5.volatile-lru:当内存不足以容纳新写入数据时,会在设置了过期时间的键中,移除最近最少使用的键。
6.volatile-lfu: lfu是在Redis 4.0 时引入,当内存不足以容纳新写入数据时,它会在设置了过期时间的键中移除最近使用频率最小的键。
7.volatile-random: 它的淘汰策略是在设置了过期时间的键值对中,进行随机移除。
8.volatile-ttl: 它的淘汰策略是当内存不足以容纳新写入数据时,会在设置了过期时间的键空间中,移除即将过期的键。
三、LRU和LFU算法分析
1.LRU算法
LRU 算法的全称是 Least Recently Used,即按照最近最少使用的原则来淘汰数据。把最不常用的数据筛选出来,而最近频繁使用的数据则会留在缓存中。
(1)LRU 会把所有的数据组织成一个链表,链表的头和尾分别表示 MRU 端和 LRU 端,分别代表最近常使用的数据和最近不常用的数据。
LRU算法其实可以这样理解,就是认为刚刚访问的数据可能还会被访问到,就会放在MRU端,长时间不访问的数据放在LRU端,缓存满了就删除它。
不过,LRU 算法在实际实现时,需要用链表管理所有的缓存数据,这会带来额外的空间开销。而且,当有数据被访问时,需要在链表上把数据移动到 MRU 端,如果有大量的数据被访问,就会带来很多链表移动操作,会耗时,进而降低 Redis 缓存性能。
因此在 Redis 中,LRU 算法被做了简化,以减轻数据淘汰对缓存性能的影响。具体来讲,就是Redis 默认会记录每个数据最近一次访问的时间戳(由键值对数据结构 RedisObject 中的 lru 字段记录)。然后redis在淘汰数据时会随机选出N个数据,作为一个候选集合,接下来redis会比较这N个数据的lru字段。把其中最小的淘汰出去。
(2)Redis 提供了一个配置参数 maxmemory-samples,这个参数就是 Redis 选出的数据个数 N。例如,我们执行如下命令,可以让 Redis 选出 100 个数据作为候选数据集:
CONFIG SET maxmemory-samples 100
当需要再次淘汰数据时,Redis 需要挑选数据进入第一次淘汰时创建的候选集合。这儿的挑选标准是:能进入集合数据的lru字段必须小于集合中最小的lru值。当有新数据进入候选数据集后,如果候选数据集中的数据个数达到了 maxmemory-samples,Redis 就把候选数据集中 lru 字段值最小的数据淘汰出去。
这样Redis 缓存不用为所有数据维护一个大表,也不用在每次数据访问时都移动链表项,提升了缓存的性能。
2.LFU算法
LFU(Least Frequently Used)是Redis 4.0 引入的淘汰算法,它通过key的访问频率、访问时间比较来淘汰key,重点突出的是Frequently Used,LFU 算法更加重视元素的访问频率,而非最近一次访问时间。
(1)LFU算法根据缓存块的使用频率来决定哪些块应该被清除。具体来说,它会记录每个缓存块的使用次数,并按照使用次数从低到高排序。当缓存达到容量上限时,LFU算法会选择使用次数最少的缓存块进行清除,也就是最不经常使用的缓存块。
LFU算法的优点是能够有效地防止缓存溢出,并且能够最大限度地减少清除重要数据的概率。但是,由于需要记录每个缓存块的使用次数,因此LFU算法需要较大的内存空间,并且由于需要经常更新使用次数,因此其时间复杂度相对较高。
(2)Redis LFU 缓存淘汰算法。
Redis 中实现了基于 LFU 的缓存淘汰策略:volatile-lfu 和 allkeys-lfu。
Redis使用LFU策略淘汰数据时,选择 lru 字段最小的数据进行淘汰。等价于 优先淘汰访问次数少的数据,访问次数相等则淘汰时间戳最小 的数据。
总结:
在实际应用中,选择哪种淘汰策略取决于应用的需求和数据的重要性。对于重要的数据,应选择能够保留数据的策略,如volatile-lru,而对于非关键数据,可以选择随机淘汰random策略,或者完全不淘汰noeviction策略。