Redis数据淘汰策略 LRU深入分析 (二)

目录

Redis数据淘汰策略 概论 (一)
Redis数据淘汰策略 LRU深入分析 (二)
Redis数据淘汰策略 LFU深入分析 (三)

1.前言

上篇文章我们整体上介绍了redis的淘汰策略,而其中LRU和LFU两种算法又是极其重要的,接下来我们从底层原理开始逐一揭开它们的神秘面纱!

2. LRU

2.1 LRU

LRU(least recently used),从字面上理解是最近最少使用的,会淘汰掉最近最不曾使用的key;
有兴趣可查看redis官方文档关于这块的介绍,点击查看

实现LRU算法除了需要key/value字典外,还需要附加一个链表,聊表中元素按照一定顺序排列,当空间满的时候就剔除尾部的元素,当字典的某个元素被访问时,他在链表中的位置会被移动到表头,所以链表的元素排列顺序就是元素最近被访问的时间顺序
在这里插入图片描述
分析:

  • 优点:链表元素的排列顺序就是元素最近被访问的时间顺序,清晰明了
  • 缺点:每次需要把整个链表进行很大的变动,会消耗大量的额外内存;同时,加入有一个元素很久没有被删除,使用频率很低,最近使用一次,那么这个使用频率很低的元素也不会被淘汰掉,这也是后续出现更好的lfu算法的原因;

2.2 近似LRU
redis实际上采用的是近似LRU算法,从我们刚提到的LRU的缺点就能理解这一点;
在这里插入图片描述

如下图是随机LRU算法和严格LRU算法的效果对比图
在这里插入图片描述
图中绿色部分是新加的key,深灰色部分是老旧的key,浅灰色部分是通过LRU算法淘汰掉的key;从图中可以看出采样数量越大,近似LRU算法的效果越接近严格LRU算法,同时Redis3.0在算法中增加了淘汰池,进一步提升了近似LRU算法的效果;

拓展: 淘汰池其实是一个数组,它的大小是maxmemory_samples,在每次淘汰循环中,新的随机得到的key列表会和淘汰池中的key列表进行一次融合,即求并集后淘汰最旧的key,保留剩余较旧的key列表放入淘汰池中留待下一个循环。

2.3 redis请求头与 LRU

redis为了实现近似LRU,给每个key增加了一个额外的小字段,长度为24bit(默认存的是Unix时间戳对2^24取模的结果,大约97天清零一次),当某个key被访问一次,它的对象头结构中lru字段就会被更新为server.lruclock;
如果server。lruclock没有折返(对2^24取模),它就是一直递增的,意味着对象的lru字段不会超过server.lruclock的值,如果超过了,说明折返了,通过这个逻辑就可以计算出对象多长时间没有被访问-----即“对象的空闲时间”;

空闲时间计算如下
在这里插入图片描述

redis对象头结构如下

struct RedisObject{
	int4 type;
	int4 encoding;
	int24 lru;
	int32 refcount;
	void *ptr;
} robj ;

3.总结

redis实际上使用的是近似LRU算法

使用频率很低的元素如果最近被使用过一次,在很长的一段时间也不会被淘汰掉,这也是LFU算法出现的原因

4.思考

如果你是java用户,如何使用LinkedHashMap实现一个LRU字典?

最后,如果看完对你有所帮助,不要吝啬关注 / 点赞 / 收藏哟,感谢感谢~

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值