redis事务oom失败时,discard无效,因exec已触发执行;maxmemory-policy决定事务能否“软着陆”,需在multi前预估value大小、监控内存水位并拆分大事务。

Redis事务因OOM被拒绝时,DISCARD无法恢复内存状态
当EXEC返回(error) OOM command not allowed when used memory > 'maxmemory',说明事务中某条命令(如SET大值)触发了Redis的内存保护机制。此时事务已部分执行——前面成功的命令(如INCR、DEL)已完成,而失败命令之后的指令仍会继续尝试执行。但DISCARD对这种情况完全无效:它只在EXEC前清空队列,一旦进入EXEC阶段,事务已提交执行,DISCARD根本不可用。
maxmemory-policy配置直接影响事务是否能“软着陆”
内存满时的行为不取决于事务本身,而由maxmemory-policy决定。不同策略下事务失败的表现差异极大:
-
noeviction(默认):直接拒绝写命令,EXEC中任意写操作失败即报OOM,后续命令照常执行 -
allkeys-lru或volatile-lru:可能自动驱逐key腾出空间,使部分写命令“侥幸”成功,但驱逐不可预测,事务结果不稳定 -
allkeys-random等策略:驱逐行为更不可控,可能误删关键业务key,导致数据逻辑错误
注意:WATCH + MULTI无法绕过OOM限制——监视的key即使未被修改,只要EXEC时内存超限,照样失败。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
真正有效的应对方式不是靠事务命令,而是前置控制
靠EXEC时兜底是徒劳的。必须在事务组装阶段就规避OOM风险:
- 对要写入的value做长度预估,比如JSON字符串先
strlen,超过阈值(如512KB)直接拒绝,不进MULTI - 用
INFO memory定期采样used_memory_human和mem_fragmentation_ratio,在客户端层建立水位告警,流量高峰期主动降级非核心事务 - 拆分大事务:把单个含10个
SET的事务,改为2个各含5个的事务,并在每次EXEC后检查used_memory增量 - 避免在事务中混用读写——
GET类只读命令不会触发OOM,但无意义地塞进事务反而增加队列负担和执行时间窗口
监控和日志里最容易被忽略的关键点
生产环境排查OOM事务失败时,90%的人只看EXEC返回的错误,却漏掉三个隐藏线索:
-
redis-cli --stat输出中的evicted_keys计数突增,说明策略已开始驱逐,事务成功率正在下滑 -
SLOWLOG GET里出现大量EXEC耗时飙升(>100ms),往往是内存碎片化+驱逐IO叠加导致 - AOF重写期间
used_memory会临时上涨30%~50%,此时maxmemory应预留缓冲,不能卡死在100%
事务不是内存问题的解法,而是放大器——它把多个写操作捆在一起执行,等于把OOM风险集中爆发。真正的防线在MULTI之前,不在EXEC之后。










