(转帖)Redis的LRU和LFU区别

  • 常见的缓存算法:

  • LRU (Least recently used) 最近最少使用,如果数据最近被访问过,那么将来被访问的几率也更高。
  • LFU (Least frequently used) 最不经常使用,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小。
  • FIFO (Fist in first out) 先进先出, 如果一个数据最先进入缓存中,则应该最早淘汰掉。





一:LRU

Redis维护了一个24bit(位)时钟,可以简单理解为当前系统的时间戳,每隔一定时间会更新这个时钟。每个key对象内部同样维护了一个24位的时钟,当新增key对象的时候会把系统的时钟赋值到这个内部对象时钟。比如我现在要进行LRU,那么首先拿到当前的全局时钟,然后再找到内部时钟与全局时钟距离时间最久的(差最大)进行淘汰,这里值得注意的是全局时钟只有24位,按秒为单位来表示才能存储194天,所以可能会出现key的时钟大于全局时钟的情况,如果这种情况出现那么就两个相加而不是相减来求最久的key。

二:LFU

LFU是在Redis4.0后出现的,LRU的最近最少使用实际上并不精确,edis于4.0.3版本开始正式支持基于LFU的热点key发现机制。考虑下面的情况,A距离的时间最久,但实际上A的使用频率要比B频繁,所以合理的淘汰策略应该是淘汰B。LFU就是为应对这种情况而生的。

redis中每个对象都有24 bits空间来记录LRU/LFU信息,用作LFU时,其被分为两部分:

1:高16位用来记录访问时间(单位为分钟)

2:低8位用来记录访问频率,简称counter

8 bits最大值也就是255,只用8位来记录访问频率肯定是不够用的。Redis用了一个trick的手段,counter并不是一个简单的线性计数器,而是用基于概率的对数计数器来实现

1:counter:基于概率的对数计数器

2:counter的衰减因子

随着key的访问量增长,counter最终都会收敛为255,这就带来一个问题,如果counter只增长不衰减就无法区分热点key

为了解决这个问题,redis提供了衰减因子server.lfu_decay_time,其单位为分钟,计算方法也很简单,如果一个key长时间没有访问那么它的计数器counter就要减少,减少的值由衰减因子来控制;

概率因子和衰减因子的 配置参数:

lfu-log-factor 10 lfu-decay-time 1

热点key发现

其核心就是在每次对key进行读写访问时,更新LFU的24 bits域代表的访问时间和counter,这样每个key就可以获得正确的LFU值

redis提供了OBJECT FREQ子命令来获取LFU信息,但是要注意需要先把内存逐出策略设置为allkeys-lfu或者volatile-lfu

使用scan命令遍历所有key,再通过OBJECT FREQ获取访问频率并排序,即可得到热点key。为了方便用户使用,redis 4.0.3同时也提供了redis-cli的热点key发现功能,执行redis-cli时加上--hotkeys选项即可

你可能感兴趣的:(Redis)