症状
本篇调试指南针对“Redis OOM command not allowed — maxmemory 且 noeviction”。内容涵盖可观察的症状、可复现的诊断路径、根本原因、具体修复方式,以及如何验证修复并防止回归。
可观察到的症状包括:
- 写入失败并提示 “OOM command not allowed when used memory > maxmemory”
- 读取仍可用而写入被拒
- 内存逐渐填满直至写入停止
诊断
先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。
步骤 1
redis-cli INFO memory | grep used_memory_human; redis-cli CONFIG GET maxmemory-policy maxmemory
used_memory 达到 maxmemory 且策略为 noeviction,即解释了写入被拒。
步骤 2
redis-cli --bigkeys
超大键或缺失 TTL 常是内存增长的原因。
常见诱因(按出现频率排序):
- 设置了 maxmemory 但策略为 noeviction,Redis 拒绝写入而非淘汰
- 工作集确实超出配置内存
- 大键或无 TTL 使内存无限增长
根因
设置 maxmemory 且策略为 noeviction 时,达到上限后 Redis 拒绝写入以避免数据丢失。这是有意的安全模式而非缺陷,因此要么允许淘汰,要么提供更多内存。
修复
设置合适的淘汰策略(缓存用 allkeys-lru,带过期数据用 volatile-ttl),仅在数据不可丢失时保留 noeviction,添加 TTL,拆分大键,并让实例规格匹配工作集。
注意:淘汰策略会静默丢弃键;对必须持久的数据应使用 noeviction 并扩容,而非淘汰。
# size the limit and choose a cache-friendly policy
redis-cli CONFIG SET maxmemory 2gb
redis-cli CONFIG SET maxmemory-policy allkeys-lru
# add TTLs so data expires instead of accumulating
redis-cli SET session:1 data EX 3600
# inspect
redis-cli INFO stats | grep -E 'evicted_keys|expired_keys'
验证
调整后确认写入成功且 used_memory 低于 maxmemory;验证 evicted_keys 或 expired_keys 按预期变化。
修复后补充一条回归测试,复现原始症状,防止问题再次出现。
这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。