需用redis-cli client list结合omem和cmd字段定位:omem>1mb且cmd为subscribe或空值,大概率是消费延迟的pub/sub订阅者;omem稳定几mb且cmd为monitor,说明客户端未读响应或网络卡顿;omem=0但qbuf大则问题在输入侧。

怎么看哪个client在吃输出缓冲区内存
别只盯着 INFO memory 里的 used_memory_rss,得直接揪出具体连接。关键字段是 omem(输出缓冲区字节数)和 cmd(最后执行命令),它俩组合能快速定位问题类型:
-
omem> 1MB 且cmd是subscribe或空值 → 极大概率是消费延迟的 pub/sub 订阅者,消息堆积在缓冲区没被读走 -
omem稳定在几 MB 且cmd是monitor→ 客户端没读响应,或者网络中间链路卡住 -
omem= 0 但qbuf很大 → 问题在输入侧(客户端发太快),和 output buffer 无关
用这条命令快速筛出 top 10:
redis-cli CLIENT LIST | awk -F' ''{for(i=1;i1000000) print "omem=" omem, "cmd=" cmd}' | sort -k1,1nr | head -10
为什么调小 client-output-buffer-limit 反而更危险
设成 pubsub 8mb 2mb 30 或 normal 2mb 64kb 60 看似“更严格”,实则容易触发雪崩:
- 慢订阅者每 30 秒被踢一次,但客户端若无退避重连逻辑,立刻重连+重订阅,缓冲区重新填满
- 旧连接的
omem内存不会马上释放(尤其 pub/sub 场景下可能滞留数十秒),新连接又开始分配,形成“踢-连-积-踢”循环 - 瞬时 RSS 内存飙升,
used_memory_rss比used_memory高出 2 倍以上,系统 OOM Killer 可能直接杀 Redis 进程
典型表现:client_longest_output_list 持续 >1MB,且 CLIENT LIST 中大量连接的 omem 卡在 8–30MB 不下降。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
CONFIG SET client-output-buffer-limit 怎么改才不翻车
硬限(第一个值)和软限(第二、三个值)必须协同调整,不能只改一个数字:
- pub/sub 场景:先观察峰值
omem(比如最高到 12MB),设为pubsub 64mb 16mb 120—— 给足余量,延长软限时间,避免频繁断连 - normal 场景(如压测):推荐
normal 512mb 128mb 60—— 允许突发,但连续 60 秒超 128MB 就断;切忌设成0 0 0(等于关闭保护)或2048mb 1024mb 300(掩盖执行瓶颈) - slave 场景:优先优化从库执行速度,而非盲目调大;临时可用
slave 512mb 256mb 60,同时关 AOF(CONFIG SET appendonly no)减少本地写盘阻塞
改完记得验证:CONFIG GET client-output-buffer-limit,并持续观察 client_longest_output_list 和 used_memory_rss 走势。
压测中发现缓冲区涨得快,但 used_memory 很稳,说明什么
这说明问题根本不在数据量,而在客户端没及时消费响应:
- 压测工具(如
redis-benchmark、JMeter Redis 插件)若未显式读取 reply,缓冲区会持续膨胀,最终被 Redis 主动断连 -
connected_clients持续飙升但used_memory平稳 → 典型的“发得多、收得少”,不是 Redis 数据多,是 client 在积压响应 -
used_memory_rss显著高于used_memory(ratio > 1.5),且CLIENT LIST中有长期omem>10MB 的连接 → 几乎可以确定是某个 client 卡死或网络异常
真正难处理的不是配置数字,而是那些不读响应、不加退避、不处理异常的客户端逻辑——它们不会报错,只会悄悄把 Redis 拖垮。










