不是物理内存真正耗尽,而是Redis触发写入拒绝机制:原因包括内存碎片率过高(>1.5)、maxmemory-policy为noeviction、集群单节点超限、maxmemory配置过低或缓冲区隐式占满。

直接看日志里有没有 OOM command not allowed when used memory > 'maxmemory' —— 有,就是内存写满被拒了;没有,别急着调 maxmemory,可能根本没到阈值。
日志中出现 OOM command not allowed when used memory > 'maxmemory' 怎么确认是真满了
这个错误不是“快满了”,而是“已经满了且策略不允许淘汰”,必须立刻验证两个数值:
-
used_memory和maxmemory是否真的接近(比如差值 redis-cli -p 6379 INFO memory | grep -E "(used_memory|maxmemory)" 查 -
mem_allocator是否为jemalloc(主流),避免误判内存碎片导致的伪 OOM - 检查
evicted_keys计数器是否为 0:如果是 0,说明淘汰策略压根没生效(比如配了volatile-lru但所有 key 都没 TTL) - 注意日志时间戳和
INFO stats中的latest_fork_usec:如果刚 fork 过,used_memory可能含 copy-on-write 内存,实际物理占用未必真爆
maxmemory-policy 配错时的日志表现差异
不同淘汰策略触发时,Redis 日志行为完全不同,不能只盯 OOM 错误:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
noeviction(默认):只报 OOM,evicted_keys永远为 0,expired_keys不受影响 -
volatile-lru或volatile-ttl:若evicted_keys为 0 但used_memory_human接近maxmemory_human,大概率是业务写入的 key 全都没设 TTL,策略失效 -
allkeys-lru或allkeys-lfu:会持续增加evicted_keys,但日志里通常不打具体淘汰了谁——得靠redis-cli --bigkeys或MEMORY USAGE手动查大 key -
volatile-random/allkeys-random:不会产生明显日志特征,但evicted_keys会涨,需结合监控看突增是否匹配业务批量写入节奏
为什么 CONFIG SET maxmemory 立刻生效但日志没变
运行时调大 maxmemory 后,旧的 OOM 错误可能还会持续几秒,原因很实际:
- 客户端连接可能复用旧的连接池配置,部分请求仍按旧阈值校验(特别是 Jedis/Lettuce 未刷新连接状态时)
- Redis 的内存统计是周期性采样(默认每 100ms 更新一次
used_memory),刚改完还没来得及重算 - 如果之前触发过
evict流程,正在异步释放 bigkey,释放过程本身会卡住命令队列,新请求继续排队等,看起来像“没生效” -
CONFIG SET maxmemory-policy必须在maxmemory已设的前提下才起作用;单独改策略、不设maxmemory,等于没开淘汰开关
真正要盯的日志和指标,不是错误本身
OOM 错误只是结果,真正该实时监控的是这几个字段:
-
used_memory_peak_human:历史峰值,比当前used_memory更能暴露突发写入问题 -
mem_fragmentation_ratio> 1.5 时,说明内存碎片严重,used_memory看似没满,但实际分配失败频繁 -
expired_keys短时间暴涨(比如 1 秒内 +1000),可能触发集中过期 + 淘汰双重压力,延迟飙升 -
evicted_keys持续非零增长,但used_memory不降反升 → 很可能是写入速度远超淘汰速度,或者淘汰的都是小 key,腾不出足够空间
别只翻 error.log,INFO memory 和 INFO stats 的输出才是真实水位计。很多线上事故,是在 OOM 出现前 2 小时,evicted_keys 就开始缓慢爬升,但没人去看。

















