必须同时设置maxmemory和maxmemory-policy,缺一或拼写错误(如no-eviction、noeviction)均导致策略不生效,redis退回到默认行为,内存持续增长直至触发oom killer;config get maxmemory-policy返回必须为全小写无空格的标准值,且evicted_keys持续为0即表明淘汰未运行。

maxmemory-policy 配置缺失或拼写错误
Redis 不会自动触发淘汰,除非你明确设置了 maxmemory-policy。只配 maxmemory 而没设策略,Redis 会退回到默认行为(高版本默认是 noeviction,但低版本可能是 volatile-lru),而这个“默认”并不可靠——尤其在配置被覆盖、升级或通过 CONFIG SET 动态修改后容易丢失。更常见的是拼写错误:no-eviction、NoEviction、noevition 等都会导致策略不生效,Redis 实际运行时等同于未配置。
验证方式很简单:
- 执行
redis-cli CONFIG GET maxmemory-policy,输出必须是noeviction或allkeys-lru这类标准值(全小写、无空格、无连字符) - 若返回
""或(nil),说明策略根本没加载成功 - 同时检查
INFO memory中的evicted_keys:若长期为 0,且used_memory持续逼近maxmemory,基本可断定淘汰逻辑压根没跑
用了 volatile-lru / volatile-lfu 却全是永久键
这类策略只看带 TTL 的 key,对 SET user:1001 "Alice" 这种没加 EX 或 PX 的键完全无视。哪怕内存爆满,Redis 也像 noeviction 一样直接拒绝写入,报 (error) OOM command not allowed when used memory > 'maxmemory'。
快速确认方法:
- 用
SCAN 0 MATCH * COUNT 1000扫一批 key,再对每个 key 执行TTL keyname - 如果大部分返回
-1(永久)或-2(key 不存在),说明数据生命周期和策略严重错配 - 业务代码中缓存写入路径是否漏了
EX?比如用SETNX替代SETEX,或者 ORM 层自动封装时跳过了过期设置
策略设对了,但 evicted_keys 仍不增长
即使 maxmemory-policy 是 allkeys-lru,evicted_keys 也可能卡住不动——这不是策略失效,而是 Redis 淘汰机制本身有延迟和采样限制。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
原因包括:
-
allkeys-lru是随机采样(默认 5 个 key),淘汰其中空闲时间最长的;如果当前所有活跃 key 都刚被访问过,采样可能反复落空 - 内存碎片率高(
mem_fragmentation_ratio > 1.5)时,Redis 可能无法 malloc 新空间来完成淘汰动作,导致逻辑阻塞 - 客户端缓冲区(client-output-buffer-limit)占满,Redis 会优先保护连接,暂停淘汰逻辑
- 主从复制中,从库
maxmemory设得比主库小,但主库正大量写入,从库可能因驱逐不及而卡死同步,间接抑制淘汰
noeviction 策略下误以为该淘汰却没动
noeviction 的设计就是“不淘汰”,它只做一件事:当 used_memory >= maxmemory 时,所有写命令(SET、HSET、LPUSH 等)立刻返回 OOM 错误。它不会删任何 key,也不会腾出哪怕一个字节。
如果你期望“写失败后自动清理”,那说明你其实不该用 noeviction。这种策略只适合两类场景:
- 纯配置中心类实例(如
redis-config),所有 key 必须永久存在 - 应用层已自行实现降级/重试/熔断,能稳定捕获
(error) OOM command not allowed...并作出响应
真正容易被忽略的是:noeviction 不是“保守策略”,而是“零容忍策略”。它把内存控制权完全交还给上层,一旦配置或容量预估出错,故障会立刻暴露,而不是悄悄丢数据。










