Redis内存淘汰在每次写命令前触发,检查是否超maxmemory,超限则按策略淘汰少量key;读操作不触发,未配maxmemory则不启用淘汰。

Redis 内存淘汰由什么条件触发
Redis 不是等到内存爆了才开始淘汰,而是在每次执行写命令前,先检查当前内存是否超过 maxmemory 配置值。只要这次写入会让内存超限,就立刻按配置的策略淘汰一部分 key。
- 淘汰动作只发生在写操作中(如
SET、LPUSH、HSET),读操作(如GET、HGETALL)完全不触发 - 如果没配
maxmemory,或者设为 0(Linux 默认行为),则不启用淘汰机制,内存可能无限增长 - 淘汰不是一次性清空到安全水位,而是每次只淘汰少量 key(默认 5 个),再重试写入;若仍超限,继续淘汰,直到成功或无 key 可删
不同淘汰策略的实际行为差异
maxmemory-policy 决定了“挑谁删”,但每种策略的触发时机和效果差别很大:
-
noeviction:不淘汰,直接返回(error) OOM command not allowed when used memory > 'maxmemory'.—— 最安全,但业务必须自己兜底 -
allkeys-lru/allkeys-lfu:在所有 key 中选,适合缓存场景,但会误伤长期不用但仍有价值的冷数据 -
volatile-lru/volatile-ttl:只淘汰带过期时间的 key,适合把 Redis 当纯缓存 + 临时状态混合用的场景;但如果大量 key 没设EXPIRE,就等于“失效策略” -
volatile-lfu和allkeys-random在低频访问或 key 分布不均时容易出现淘汰抖动(刚写入就被删)
注意:lfu 策略依赖访问计数器,计数器不是实时更新,有衰减周期(默认 1 分钟),所以“最近最不常用”其实是近似值。
为什么设置了 maxmemory 却没看到淘汰日志
Redis 默认不打印淘汰动作的详细日志,只在 info 输出里体现结果:
- 查看淘汰统计:运行
INFO stats,关注evicted_keys字段是否在增长 - 查看当前内存压力:用
INFO memory,比对used_memory和maxmemory - 淘汰不明显,常见原因:
- 写入速率低,淘汰后内存暂时回落,下一次触发间隔长
- 使用了
noeviction或volatile-*但大部分 key 没过期时间 - 客户端收到
OOM错误却没捕获,误以为“没淘汰”,其实是拒绝写入了
淘汰动作对性能和延迟的影响
淘汰本身不是零成本:
- 每次淘汰都要扫描候选 key 集合(比如 LRU 要查空闲链表,LFU 要算频率分值),CPU 开销随候选集增大而上升
- 若策略是
allkeys-lfu且 key 数量达千万级,单次淘汰可能耗时毫秒级,叠加网络往返,P99 延迟会明显上扬 - 更隐蔽的问题:淘汰引发的 key 失效,可能让上游服务突然大量回源,造成雪崩——这不是 Redis 的问题,但它是淘汰机制的自然后果
真正难处理的,是 volatile 策略下那些“忘了设过期时间”的 key:它们既占内存又躲过淘汰,时间一长,used_memory 会缓慢爬升,直到某次突发写入直接触顶。










