不能关闭noeviction,它是内存淘汰策略而非开关;安全切换需满足maxmemory已设且合理、当前策略确为noeviction、内存持续超限且mem_oom_events增长。

不能“关闭”noeviction——它不是开关,而是策略值;安全切换的关键是确认淘汰能真实生效,而不是只改配置。
为什么CONFIG SET maxmemory-policy allkeys-lru后业务还在报OOM
改策略本身不保证淘汰启动,必须同时满足三个硬性条件:
-
maxmemory已设置且值合理(比如2gb),否则 Redis 根本不进入内存检查流程 - 当前策略确实是
noeviction(用redis-cli CONFIG GET maxmemory-policy验证,注意大小写和空格) - 内存已持续超限:仅靠单次写入触发不够,
INFO memory中的mem_oom_events必须在增长,说明拒绝已发生
常见误操作:改完策略立刻查 evicted_keys,发现还是 0 就以为失败——但该指标只在淘汰真正执行后才累加,而首次淘汰需先触发超限+写命令+循环释放,中间有延迟。
allkeys-lru 是最稳妥的替换策略,但要注意数据特征
相比 volatile-lru 或 volatile-ttl,allkeys-lru 不依赖 key 是否设了 TTL,所有 key 都参与 LRU 排序,适合缓存写入不可控、部分 key 无过期时间的场景。
- 若业务中存在长期存活的全局配置(如
config:feature_flags),allkeys-lru可能误删——应单独分库或用SET+EXPIRE显式控制生命周期 -
allkeys-lfu在低频访问下易误判(默认lfu-log-factor 10),冷 key 被当成热 key 留着,该淘汰的没淘汰 -
allkeys-random淘汰完全随机,刚写入的热点 session key 可能被秒删,生产环境慎用
切策略前必须验证的三件事
跳过这三步,90% 的线上切换会失效或引发误删:
- 运行
redis-cli memory doctor:它会指出隐性内存占用,比如client-output-buffer堆积或slave_buf卡住,这些不体现在used_memory里,但会让真实可用内存为负 - 检查
mem_fragmentation_ratio:若 > 1.5,说明内存碎片严重,RSS 占用远超逻辑内存,即使used_memory_human显示还有余量,实际已无法分配新页 - 观察
evicted_keys是否持续增长:改完策略后,手动发几条SET命令(确保会涨内存),再查INFO memory。如果evicted_keys不动,说明淘汰逻辑根本没跑起来——可能是maxmemory没设,或策略拼错(如写成no-eviction)
临时恢复写入比切策略更快
业务正在报错时,优先保服务,再调策略:
- 立即清理非核心 key:
redis-cli --scan --pattern "tmp:*" | xargs -r redis-cli del(比FLUSHDB安全得多) - 若主从同步卡顿,
client-output-buffer-limit slave可能已吃掉数百 MB,执行redis-cli CLIENT UNBLOCK或临时CONFIG SET client-output-buffer-limit "normal 0 0 0 slave 256mb 64mb 60 pubsub 32mb 8mb 60" - 大 key 是隐形杀手:用
redis-cli --bigkeys扫描,重点看hash或zset类型中单个 key > 1MB 的,它们删除后内存未必立刻归还(lazy-free 未完成),需盯used_memory_peak_human是否回落
真正容易被忽略的是:策略切换后,CONFIG GET 返回正确 ≠ 淘汰在工作;evicted_keys 为 0 也不等于没风险——它可能只是还没来得及触发第一次淘汰循环。











