← 中文资源

简体中文版本

Redis OOM command not allowed — maxmemory 且 noeviction

通过选择淘汰策略、设置 maxmemory 并调整实例规格,修复 “OOM command not allowed when used memory > maxmemory”。

阅读英文原文

症状

本篇调试指南针对“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 按预期变化。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。