Redis OOM command not allowed 怎么解决?maxmemory、淘汰策略与容量预算

2026-09-20

直接答案:Redis 返回 OOM command not allowed when used memory > maxmemory,说明写命令触发了内存上限且当前策略无法释放足够键,常见于 noeviction、只有无 TTL 键却使用 volatile 策略,或单个大键/客户端缓冲突增。先保存 INFO memory、INFO stats、CONFIG GET maxmemory* 和 keyspace 证据,明确 Redis 是可重建缓存、会话还是唯一业务数据,再决定过期/淘汰、优化数据结构、限制客户端、扩容或分片。不要直接 FLUSHALL。

本文适合 Redis 写入报 OOM、应用出现缓存/会话异常或服务器内存快速增长。Linux OOM Killer 杀进程是另一个层次:即使 Redis 没设 maxmemory,宿主仍可能被耗尽;需要同时给操作系统、复制/AOF缓冲和其他服务留余量。

本文按 2026 年 9 月可查的官方文档核对。示例命令以只读取证为主;凡涉及删除、覆盖、重启、权限、网络或数据库参数的动作,都应先确认操作对象、备份、维护窗口和带外恢复入口。不同发行版与软件版本的路径可能不同,必须先查询实际配置再改。

先用证据判断故障在哪一层

现象或检查点 它能说明什么 直接证据 不要误判为
used_memory接近maxmemory且noeviction 达到配置上限后拒绝写 INFO memory与CONFIG GET 宿主已完全没内存
volatile策略但无过期键 没有符合淘汰条件的键 keyspace expires与策略 Redis策略未生效
used_memory_dataset不大但RSS高 碎片、fork或分配器峰值 RSS、fragmentation与持久化时间 全是有效数据
输出缓冲很大 慢客户端/订阅或大响应占内存 client list与buffer指标 键空间增长
单个键巨大 数据模型或批量值问题 MEMORY USAGE与抽样 连接数过多

这张表的用法不是“看到一个关键词就改一个参数”,而是把客户端、DNS或边缘、Web 代理、应用、数据层依次分开。至少保留故障时间、完整 URL、状态码、关键响应头、同一时刻的服务日志和一份正常样本。只有时间能够对齐,才能判断两个现象是否属于同一次故障。

六步排查与修复顺序

1. 先保存内存与策略快照

记录故障时间、应用错误、Redis版本、角色、INFO memory/stats/keyspace/clients/persistence 和 maxmemory 配置。不要在证据前执行大量 scan、删除或重启;高负载下昂贵命令会进一步影响延迟。

2. 明确数据是否允许淘汰

将键分为可重建缓存、会话/限流状态、队列和权威业务数据。缓存可选择 LRU/LFU 等策略,权威数据应优先扩容、分片和持久化,不能为了恢复写入随机丢键。

3. 核对策略与TTL覆盖

volatile-* 只处理设置过期的键;如果大多数键无 TTL,会出现内存满却无法淘汰。统计 expires 与 evicted_keys,抽样确认关键键 TTL,避免批量补 TTL 误删永久数据。

4. 寻找大键和非数据内存

使用 MEMORY USAGE、采样/诊断工具识别大键和不合理数据结构,查看客户端输出缓冲、复制/AOF缓冲和碎片。不要在生产高峰运行阻塞式全库命令;优先采样和副本。

5. 按根因选择最小处置

可重建缓存可在确认后删除特定命名空间或调整合适淘汰策略;泄漏客户端应限缓冲并修消费者;权威数据不足则扩内存、分片或迁移。设置 maxmemory 时给系统和持久化 fork 留余量。

6. 用业务行为验收而非只看内存

修复后验证写入、读取、会话、队列和命中率,观察 used_memory、RSS、evicted_keys、rejected_connections、延迟和宿主 swap/OOM。跨过持久化重写与流量高峰,确保不会再次越界。

可复制的只读取证命令

以下命令中的域名、服务名、路径和时间范围要替换为自己的真实值。先执行查询命令并保存原始输出;不要把“命令能运行”误当成“业务已恢复”。

text redis-cli INFO memory redis-cli CONFIG GET maxmemory maxmemory-policy redis-cli INFO keyspace redis-cli INFO stats | grep -E 'evicted_keys|keyspace_hits|keyspace_misses|rejected_connections' redis-cli MEMORY USAGE your:key SAMPLES 5

  • redis-cli INFO memory:保存Redis数据、RSS、碎片和非数据内存指标
  • redis-cli CONFIG GET maxmemory maxmemory-policy:读取当前上限与淘汰策略
  • redis-cli INFO keyspace:查看每个数据库的键数和带过期键数量
  • redis-cli INFO stats | grep -E 'evicted_keys|keyspace_hits|keyspace_misses|rejected_connections':观察淘汰、命中与拒绝趋势
  • redis-cli MEMORY USAGE your:key SAMPLES 5:对已知候选大键做采样估算,替换键名且勿公开敏感业务标识

如命令输出包含公网 IP、用户名、Cookie、令牌、数据库连接串或客户数据,分享工单前先脱敏。对比时保留时间戳、时区和命令本身,否则后来无法复现同一观察条件。

五个最容易扩大故障的误区

  • FLUSHALL 立即清空:可能删除会话、队列或唯一业务数据,且无法靠回滚配置恢复。
  • 随便改成 allkeys-random:若Redis不只是缓存,会不可预测地丢关键键。
  • maxmemory等于整机内存:没有给系统、fork、缓冲和其他进程留空间,宿主可能OOM。
  • 只看 used_memory 不看 RSS:碎片、fork和客户端缓冲会影响真实物理内存。
  • 生产高峰执行全库大扫描:诊断本身可能阻塞或增加负载。

变更、回滚与数据边界

策略和 maxmemory 变更前保存配置、INFO 快照和关键数据备份。若新淘汰策略导致会话、队列或业务键丢失,应立即停止进一步淘汰、恢复原策略并按备份/上游数据重建;已经淘汰的键不能通过改回策略恢复。扩容或迁移要验证复制、持久化和应用连接切换,避免双写分叉。

如果只能先恢复服务、还不能确认根因,应把措施标记为“临时缓解”,例如限流、摘除单节点、切回上一配置或临时绕过一层代理。恢复后仍要在受控环境复现原因,并验证同类故障不会在下一次重启、发布或高峰重新出现。

统一验收清单

  • [ ] Redis角色与数据可淘汰边界已书面确认
  • [ ] INFO与maxmemory策略快照已保存
  • [ ] TTL覆盖和evicted_keys可解释
  • [ ] 大键、缓冲与碎片已评估
  • [ ] 宿主与持久化留有内存余量
  • [ ] 业务写入不再OOM
  • [ ] 命中率、会话或队列未异常
  • [ ] 跨过AOF/RDB与高峰后内存曲线稳定

验收必须同时覆盖机器内部和真实外部路径。首页返回 200 不能证明上传、长连接、登录、数据库写入或移动端都正常;同样,控制台显示“运行中”也不能证明应用已能处理请求。至少选一个正常请求、一个边界请求和一个失败请求,记录预期与实际结果。

相关内容与隔离测试入口

建议先阅读WordPress是否用Redis、云服务器内存不足、Spring Boot服务器配置,把本问题放回完整请求链路。若生产环境不适合直接试验,可查看美国弹性云服务器的当前规格与库存,搭建与生产隔离的复现环境;测试机不能替代生产备份,价格、库存和可选配置以实时产品页为准。

常见问题

noeviction 是不是最安全?

它避免Redis主动淘汰键,但达到上限会拒绝写。是否安全取决于应用能否处理失败和数据角色。

volatile-lru 为什么不释放内存?

它只在带过期时间的键中选择;若没有合适键或释放速度不足,仍会OOM。

删除键后RSS为什么没下降?

分配器可能保留内存供Redis后续复用,RSS不会与逻辑数据同步下降。应结合 used_memory 和碎片解释。

可以把 maxmemory 设为0吗?

64位系统中通常表示不设数据上限,可能持续占用宿主内存。生产应按容量与安全余量规划。

Redis只做缓存还需要备份吗?

若确实可从权威数据重建,备份要求可降低,但仍需验证重建时间、缓存雪崩和配置恢复;不要只凭名称判断。

官方参考资料

最近更新