调小 client-output-buffer-limit 反而可能触发 oom,因为更早断连导致大量客户端瞬时重连重订阅,形成“踢-连-积-踢”循环,旧缓冲区内存未及时释放,叠加新连接内存分配,引发瞬时内存尖峰。

为什么调小 client-output-buffer-limit 反而触发 OOM
不是限制设得越严就越安全。Redis 在输出缓冲区超限时会强制断开客户端,但断连不等于内存立刻释放——尤其是 pub/sub 场景下,旧连接的 omem 内存可能滞留数十秒,而客户端若无退避逻辑(比如立刻重连+重订阅),新连接马上又开始堆积。结果就是“踢一个、来两个、积三倍”,瞬时 RSS 内存飙升。
典型表现:used_memory_rss 比 used_memory 高出 2 倍以上,client_longest_output_list 持续 >1MB,且 redis-cli CLIENT LIST 中大量连接的 omem 卡在 8–30MB 不下降。
- 默认
pubsub 32mb 8mb 60已足够应对多数业务;改成8mb 2mb 30后,慢订阅者每 30 秒被踢一次,但重连后从头订阅,缓冲区重新填满 -
normal类型若被误配成2mb 64kb 60(常见于压测后忘记还原),会导致 pipeline 或 monitor 客户端极容易被断 - 断连引发的重试风暴,在集群中还会放大:一个节点抖动 → 多个客户端重连 → 其他节点缓冲区也跟着涨
怎么定位真正吃内存的 client
别只看 INFO memory,要直接查每个连接的实时缓冲区占用。关键是过滤出 omem(输出缓冲区字节数)和 cmd(最后命令),再排序。
用这条命令快速揪出问题 client:
Redis 8.2.3 是一款安全优先的高性能键值存储系统。该版本紧急修复了可能引发远程代码执行(RCE)的高危漏洞(CVE-2025-62507),并解决了 HyperLogLog 及 Cuckoo Filter 等数据结构在特定场景下的崩溃问题。建议所有用户立即升级,以保障生产环境的系统稳定与数据安全。
redis-cli CLIENT LIST | awk -F' ' '{for(i=1;i1000000) print "omem=" omem, "cmd=" cmd}' | sort -k1,1nr | head -10
-
omem>1MB 且cmd是subscribe或空值 → 极大概率是消费延迟的 pub/sub 订阅者 -
omem稳定在几 MB 且cmd是monitor→ 客户端没读响应,或网络卡在中间 -
omem=0但qbuf很大 → 问题在输入侧(客户端发太快,Redis 还没来得及解析),和 output buffer 无关
CONFIG SET client-output-buffer-limit 怎么改才不翻车
硬限(hard limit)和软限(soft limit + seconds)必须配合调整,不能只加数字。设太高掩盖问题,设太低引发雪崩。
- pub/sub 场景:先观察峰值
omem,比如发现最高到 12MB,则设为pubsub 64mb 16mb 120(给足余量,延长软限时间) - normal 场景(如压测):避免用
0 0 0,推荐normal 512mb 128mb 60—— 允许突发,但连续 60 秒超 128MB 就断,防止单个 client 锁死整个实例 - slave 场景:若主从延迟大,
slave 512mb 256mb 120比默认更稳妥,但需同步检查repl-backlog-size是否匹配 - 所有修改必须搭配
CONFIG REWRITE持久化,否则重启失效;压测完务必恢复生产值
缓冲区问题为什么比数据量问题更难排查
它不留下大 key,不触发淘汰策略,redis-cli --bigkeys 查不到,MEMORY USAGE 也统计不到——因为 omem 是 per-connection 的 runtime 内存,不属于键值数据范畴。
真正危险的是:你看到 used_memory 才 2GB,以为还有空间,但 used_memory_rss 已经 8GB,其中 5GB 是几百个 client 的输出缓冲区在吃内存。等你反应过来,OOM 已经发生三次了。










