Redis内存淘汰

缓存淘汰策略

不进行淘汰的:noeviction

淘汰设置过期时间的:volatile-random、volatile-ttl、volatile-lru、volatile-lfu(4.0后新加的)

volatile-ttl 在筛选时,会针对设置了过期时间的键值对,根据过期时间的先后进行删除,越早过期的越先被删除。

volatile-random 就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。

volatile-lru 会使用 LRU 算法筛选设置了过期时间的键值对。

volatile-lfu 会使用 LFU 算法选择设置了过期时间的键值对。

淘汰所有的:allkeys-lru、allkeys-random、allkeys-lfu(4.0后新加的)

allkeys-random 策略,从所有键值对中随机选择并删除数据;

allkeys-lru 策略,使用 LRU 算法在所有数据中进行筛选。

allkeys-lfu 策略,使用 LFU 算法在所有数据中进行筛选。

LRU算法

按照最近最少使用的原则来筛选数据,最不常用的数据会被筛选出来,而最近频繁使用的数据会留在缓存中。

LRU 会把所有的数据组织成一个链表,链表的头和尾分别表示 MRU 端和 LRU 端,分别代表最近最常使用的数据和最近最不常用的数据。

LRU 算法选择删除数据时,都是从 LRU 端开始,所以把刚刚被访问的数据移到 MRU 端,就可以让它们尽可能地留在缓存中

但是lru算法是链表结果的,会带来大量的空间移动会消耗大量资源。

Redis LRU算法淘汰原理

Redis会通过配置的参数取值N(CONFIG SET maxmemory-samples 100),在这里就是100个。

Redis 默认会记录每个数据的最近一次访问的时间戳(由键值对数据结构 RedisObject 中的 lru 字段记录)。Redis 在决定淘汰的数据时,第一次会随机选出 N 个数据,把它们作为一个候选集合。接下来,Redis 会比较这 N 个数据的 lru 字段,把 lru 字段值最小的数据从缓存中淘汰出去。

当需要再次淘汰数据时,Redis 需要挑选数据进入第一次淘汰时创建的候选集合。这儿的挑选标准是:**能进入候选集合的数据的 lru 字段值必须小于候选集合中最小的 lru 值。**当有新数据进入候选数据集后,如果候选数据集中的数据个数达到了 maxmemory-samples,Redis 就把候选数据集中 lru 字段值最小的数据淘汰出去。

LFU内存淘汰

LFU算法是在LRU算法基础上进行了优化,正常LRU算法是根据Redisobject对象中的lru字段时间戳来判断的,但是他有一定的局限性,数据刚进来就被淘汰或者不常用的数据一直不被淘汰。所以我们引出了LFU:

LFU将lru字段24字节转成了lru字段(16字节)+counter字段(8字节),lru字段记录时间戳,counter记录被访问的次数。根据访问次数进行淘汰,当访问次数相同时再根据lru时间戳进行淘汰。因为counter字段只有8字节,那么他的最大值是255,这样我们访问超出限制的也会出现问题,所以我们增加对counter字段复制的算法:当数据被访问一次,取他的counter值*lfu_log_factor(默认是为5,LFU_INIT_VAL) 加1,取他的倒数p(100的倒数100分之一),在(0,1)区间中取任意数值r,当数值p大于r的时候counter+1.这样的话counter就不那么容易超限。下面是lfu_log_factor取值之后的counter变化趋势:

上面这些都是counter增加的情况,那么如果数据被访问上万次之后,不再被访问那么他的counter数值一直很大,我们也需要衰减情况。所以LUF又增加了衰减方案:根据当前时间减去lru字段得到差值,然后转化成N分钟,再除以lfu_decay_time,得到数值A,counter-A。

将lfu_decay_time设置为1,那么就是过去N分钟,衰减N。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值