Redis第五讲 Redis内存淘汰策略之LRU与LFU算法详细介绍

本文详细介绍了Redis中的LRU和LFU内存淘汰策略。LRU通过近似方法,利用24bit属性字段记录访问时间,通过随机采样和淘汰池提高效果。LFU则维护计数器并考虑访问频率变化,通过衰减机制减少不常用key的内存占用。Redis可通过配置调整这些算法的行为。
摘要由CSDN通过智能技术生成

前面介绍了Redis的一些内存淘汰策略,一般比较常用的两种淘汰策略为LRU,LFU,而且他们的算法考察的也比较多。

LRU(最近最久未使用)

标准LRU算法是这样的:它把数据存放在链表中按照“最近访问”的顺序排列,当某个key被访问时就将此key移动到链表的头部,保证了最近访问过的元素在链表的头部或前面。当链表满了之后,就将"最近最久未使用"的,即链表尾部的元素删除,再将新的元素添加至链表头部。其中LinkedHashMapt就可以通过访问的顺序来实现LRU算法。

一般的LRU的做法如下:
1、为每个节点设置一个prev前继节点指针和next后继节点指针,将所有节点通过这两个指针连接成一个链表,链表有着head和tail节点。
2、用一个哈希表将key和对应的节点存放起来,用来快速的找到key对应的节点
3、当通过key访问对应的节点的时候,通过哈希表查询key得到对应的节点。然后通过节点的的prev和next指针将节点从链表中移除,并将节点放到链表的头部中。
4、当新加入key和节点的时候,如果对应的链表已经满了,就将尾部的节点去除,然后将新节点加入到链表的头部。

从上述流程可以看出,基于链表和哈希表的LRU需要设置prev指针、next指针、以及hash表中的key和value的指针,这是一个很大的内存开销。

因为标准LRU算法需要消耗大量的内存,所以Redis采用了一种近似LRU的做法 给每个key增加一个大小为24bit的属性字段,代表最后一次被访问的时间戳。然后随机采样出5个key,淘汰掉最旧的key,直到Redis占用内存小于maxmemory为止。其中随机采样的数量可以通过Redis配置文件中的 maxmemory_samples 属性来调整,默认是5,采样数量越大越接近于标准LRU算法,但也会带来性能的消耗。

这里为每一个key增加的24bit的属性字段来自于RedisObject,前面的redis数据结构里面也讲过redis中的每个数据的key和value都对应着一个redisObj对象。如果忘记了Redis的几种基本数据结构,可以参考我的这篇博客:Redis第一讲 Redis五种基本类型的底层数据结构

lru值还和内存回收有关系,如果redis打开了maxmemory选项,并且内存回收算法是volatile-lru或者allkeys-lru,当内存占用超过maxmemory指定的值得时候,redis会优先选择空转时间最长的对象进行释放。

redisObj中有一个属性 lru,lru是一个24位的数字,保存了一个时间戳,代表着一个对象最新被使用的时间。

redisServer中维护了一个lruclock属性来表示当前系统的时间戳,每隔100ms就会调用updateLRUClock()来更新server.lruclock的值。
当新建key或者访问key的时候,会将对应的redisObj.lru = server.lruclock。

用server.lruclock的值减去redisObj.lru的值就可以得到对应key的空闲时间了,但是当server.unixtime也就是当前系统时间大于REDIS_LRU_CLOCK_MAX的时候,会将server.lruclock从0开始计数,这就会出现redisObj.lru大于server.lruclock的情况,这种情况下如何算对应的空闲时间呢

//这里只是粗略的估计空闲时间,因为之前算server.lruclock()和redisObj.lru的时候,已将unixtime()/REDIS_LRU_CLOCK_RESOLUTION了,对应的精度已经损失了。
unsigned  long  long  estimateObjectIdleTime(robj *o) {
     unsigned  long  long  lruclock = LRU_CLOCK();
     //正常情况,server.lruclock()还未转完一圈
     if  (lruclock >= o->lru) {
         return  (lruclock - o->lru) * REDIS_LRU_CLOCK_RESOLUTION;
     }  else  { server.lruclock(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员路同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值