LRU(Least Recently Used)最近最少使用统计算法
当Redis使用的内存超出设置的可以最大使用内存后
Redis会通过LRU的配置来回收内存
Redis对象的lru是用1<<24 - 1长度的字节表示的
可以连续标识194天的数据
Redis这里的LRU算法是近似算法
不是完全精确地获取到最合理的答案
而是按照采样结果查找到一个比较近似的结果
这个结果可能不是最合理的
但肯定不是最坏的
经典LRU算法
通过dict和linkedlist两个数据结构处理
dict记录实际数据
linkedlist记录元素的变动状态
最老的数据排在链表前面
当需要删除时
只需要按照链表顺序删除即可
LRU基本流程
Redis中LRU处理步骤
Redis的算法省去了链表的记录
而是每个对象记录了一个时间戳
通过不精确的采样获取到可删除的元素进行删除
这里是摘抄
原文
- 获取redis server当前已经使用的内存mem_reported。
- 如果mem_reported < server.maxmemory ,则返回ok。否则mem_used=mem_reported,进入步骤3。
- 遍历该redis的所slaves,mem_used减去所有slave占用的ClientOutputBuffer。
- 如果配置了AOF,mem_used减去AOF占用的空间。sdslen(server.aof_buf)+aofRewriteBufferSize()。
- 如果mem_used < server.maxmemory,返回ok。否则进入步骤6。
- 如果内存策略配置为noeviction,返回错误。否则进入7。
- 如果是LRU策略,如果是VOLATILE的LRU,则每次从可失效的数据集中,每次随机采样maxmemory_samples(默认为5)个key,从中选取idletime最大的key进行淘汰。否则,如果是ALLKEYS_LRU则从全局数据中进行采样,每次随机采样maxmemory_samples(默认为5)个key,并从中选择idletime最大的key进行淘汰。
- 如果释放内存之后,还是超过了server.maxmemory,则继续淘汰,只到释放后剩下的内存小于server.maxmemory为止。
被动淘汰 – 每次访问相关的key,如果发现key过期,直接释放掉该key相关的内存:
每次访问key,都会调用expireIfNeeded来判断key是否过期,如果过期,则释放掉,并返回null,否则返回key的值。
Redis中LRU配置
1 | # maxmemory <bytes> # 只有配置了最大使用内存,LRU才会生效,不限制内存就不需要回收了 |
LRU标记代码
1 | /* The actual Redis Object */ |
回收代码
1 | // 内存回收函数 |