Redis不用精确LRU是因为其需为每个key维护双向链表节点,每次访问都要移动节点,导致百万级key、数万QPS下CPU和内存开销过大;而近似LRU仅用24位lru字段记录逻辑时间戳,配合随机采样(默认5个)淘汰,以精度换性能与内存效率。

Redis 的 LRU 不是标准链表实现,而是用 lru 字段 + 随机采样来近似判断“最久未使用”,既省内存又扛高并发。
为什么 Redis 不用精确 LRU?
精确 LRU 需要为每个 key 维护双向链表节点,每次 GET 或 SET 都得移动节点位置 —— 这在百万级 key、数万 QPS 场景下会吃掉大量 CPU 和内存。Redis 选择牺牲一点精度,换稳定低延迟和小内存开销。
-
lru字段只占 redisObject 结构里的 24 位,记录的是“逻辑时间戳”(不是真实秒数),每次访问时更新为当前全局时钟值 - 淘汰时不遍历全部 key,而是随机抽
maxmemory-samples个(默认 5 个),从中挑lru值最小的那个淘汰 - 这个“逻辑时间戳”每 100ms 自增一次,所以即使两个 key 访问间隔小于 100ms,它们的
lru值也可能一样 —— 这就是近似的来源
如何配置并验证 volatile-lru 或 allkeys-lru?
必须同时设置 maxmemory 和 maxmemory-policy 才会触发淘汰;只设策略不设内存上限,等于没开。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 在
redis.conf中写:maxmemory 512mb maxmemory-policy volatile-lru
- 运行时动态修改:
CONFIG SET maxmemory 512mb,再CONFIG SET maxmemory-policy allkeys-lru - 验证是否生效:
CONFIG GET maxmemory和CONFIG GET maxmemory-policy必须都返回非空值 - 注意:
volatile-lru只对设置了EXPIRE的 key 生效;如果全库没一个带 TTL,那它实际退化成noeviction,写入会直接报OOM command not allowed
采样数 maxmemory-samples 调多好还是调少好?
它直接影响淘汰精度和 CPU 开销,不是越大越好,也不是越小越省。
- 默认值 5:适合大多数缓存场景,CPU 消耗低,命中率损失通常
- 设为 10 或 20:在热点高度集中的场景(比如电商首页商品缓存)下,能明显提升 LRU 效果,但单次淘汰操作的 CPU 时间会上升约 2–5 倍
- 超过 30 意义不大:边际收益急剧下降,反而可能因单次淘汰耗时过长,影响主线程响应
- 线上调整建议:先用
INFO stats查看evicted_keys和expired_keys的增长速率,再结合INFO memory中的mem_used_human波动,观察采样数变化后的实际效果
真正容易被忽略的点是:LRU 效果严重依赖访问模式 —— 如果你的业务里大量 key 只被访问一次(如临时 token、一次性验证码),它们会迅速挤占空间,但 LRU 无法区分“真冷数据”和“伪冷数据”。这时候该考虑 volatile-ttl 或混合策略,而不是硬调 maxmemory-samples。

















