Redis近似LRU无法逼近True LRU,因其lru字段仅存24位秒级时间戳、不实时更新,且淘汰依赖随机采样与16槽淘汰池,本质是工程取舍下的粗粒度筛选机制。

采样数设为10仍无法逼近True LRU的根本原因
因为Redis的近似LRU不是“调高采样数就能无限逼近”的渐进式精度模型,它从设计上就放弃了全局顺序维护——lru字段只存24位秒级时间戳,且不随每次访问实时更新(比如连续GET可能复用同一秒戳),采样再多次也无法还原被时间戳截断、被缓存未命中跳过的访问序列。
maxmemory-samples=10时的三个硬性限制
即使把maxmemory-samples调到10,以下三点仍让淘汰行为与True LRU存在不可消除的偏差:
-
lru字段是秒级精度,同一秒内多次访问的key,其“最后访问时间”完全相同,采样时无法区分谁更热 - 采样仅发生在淘汰触发瞬间,而True LRU需在每次访问时更新顺序;Redis跳过了中间所有访问事件,只保留一个快照点
- 淘汰池(eviction pool)本身只有16个槽位,即使采样10个key,最终也只从中选1个进入池子参与多轮比较——池子容量和更新频率进一步稀释了采样收益
True LRU在Redis里根本不可行的底层事实
这不是参数没调好,而是工程取舍下的必然结果:
- 每个key额外加双向链表指针,在亿级key场景下会多占上百MB内存,违背Redis“极致内存利用率”的核心定位
- 单线程中频繁链表挪动会引发cache line失效,实测在10万QPS下,这部分开销占淘汰逻辑总耗时超12%
-
OBJECT IDLETIME返回值已证明:Redis不保证访问时间戳的严格单调递增,GET和EXPIRE对lru字段的更新时机不同步,True LRU依赖的时序基础本身就不可靠
什么时候该放弃“逼近True LRU”的执念
当业务出现以下现象时,说明你在用错策略,而不是参数不够高:
- 批量扫描任务(如
HGETALL user:*)后,真实热key被大量淘汰——这是LRU固有缺陷,调maxmemory-samples到20也压不住 - 缓存命中率波动剧烈,且
evicted_keys增长与慢日志中大key读取强相关——说明冷热混杂,该换allkeys-lfu而非继续调LRU - 监控发现
lru_clock值长期卡在某几个秒级区间不动——说明访问密集到时间戳已失真,此时采样逻辑本身就在失效
真正关键的不是让LRU更“真”,而是看懂lru字段只是个粗粒度信号,它存在的意义从来不是排序,而是快速筛出“大概率可删”的候选者。











