redis不用标准lru因内存和cpu开销大;采用近似lru:随机采样maxmemory-samples个key,按lru字段排序淘汰最久未访问者;allkeys-lru全量采样,volatile-lru仅采样带过期时间的key。

Redis为什么不用标准LRU
因为标准LRU需要为每个key维护双向链表节点+指针,内存开销随key数量线性增长;每次访问都要做链表移动(O(1)但有实际CPU和cache miss成本),在亿级key场景下会明显拖慢响应。Redis选择“不精确但快”的路径——它根本没建全局访问链表。
allkeys-lru和volatile-lru的实际行为差异
两者都走同一套近似LRU逻辑,区别只在候选集范围:
-
allkeys-lru:从整个键空间随机采样,不管有没有设置expire -
volatile-lru:只从redisDb.expires字典里存在的key中采样(即设置了过期时间的key)
注意:volatile-lru对未设过期时间的key完全免疫,哪怕内存爆满也不会淘汰它们——这常被误认为“策略失效”,其实是设计如此。
近似LRU的采样与淘汰流程
Redis不扫描全量key,而是每次触发淘汰时:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 从当前db中随机选出
maxmemory-samples个key(默认5个,可配) - 对这组样本按
lru字段值排序(该字段是Redis server启动后毫秒级时间戳,每次访问key时更新) - 淘汰其中
lru值最小(即最久未访问)的那个key
这个过程每轮只淘汰1个key,若内存仍超限,会重复执行——所以你可能看到日志里连续出现多次Evicting key。这也意味着:样本数越小,淘汰准确性越低;样本数越大,单次淘汰耗时越高。
配置项maxmemory-samples的取舍
它直接控制采样精度和CPU开销的平衡点:
- 默认值
5:适合大多数缓存场景,吞吐优先 - 调高到
10或20:能提升冷热分离效果,但单次淘汰延迟上升,且对写密集型实例可能加剧延迟毛刺 - 不要设为1:退化成纯随机淘汰,
lru字段形同虚设
真正容易被忽略的是:这个参数必须在maxmemory启用后才生效,且修改后不会立即重排已有key的lru值——新访问才会刷新。










