先执行redis-cli CLIENT LIST,重点检查omem(输出缓冲区内存)、oll(待发消息数)和cmd(最后命令);omem接近硬限且oll>0即确认输出缓冲区满,而非盲目调参。

怎么看是不是输出缓冲区真满了
别一上来就改配置,先确认问题根源。执行 redis-cli CLIENT LIST,重点盯三个字段:omem(输出缓冲区内存占用,单位字节)、oll(待发送消息条数)、cmd(最后执行的命令)。
-
omem接近或超过你设的硬限(比如client-output-buffer-limit pubsub第一个值),且oll > 0→ 基本就是它了 -
omem长期为 0,但连接频繁断 → 可能根本没成功SUBSCRIBE,或客户端已断开未重连 -
oll很大但omem很小 → Redis 正在往 socket 写,卡在客户端读取或网络层
怎么快速揪出吃内存的订阅者
用这条命令筛出 omem > 1MB 的异常连接:
redis-cli CLIENT LIST | awk -F' ' '{for(i=1;i<=NF;i++) if($i ~ /^omem=/) {split($i,a,"="); omem=a[2]} else if($i ~ /^cmd=/) {split($i,b,"="); cmd=b[2]}} END{if(omem>1000000) print "omem=" omem, "cmd=" cmd}' | sort -k1,1nr | head -10
- 输出里
cmd=subscribe或cmd=(空)且omem持续在 8–30MB → 典型慢消费订阅者 -
cmd=monitor且omem稳定几 MB → 客户端没读响应,或中间网络卡住 -
omem=0但qbuf很大 → 问题在输入侧,和输出缓冲区无关
为什么调小 client-output-buffer-limit 反而更危险
设成 pubsub 8mb 2mb 30 看似“更严格”,实则容易触发雪崩:
- 慢订阅者每 30 秒被踢一次,若客户端无退避重连逻辑,立刻重连+重订阅 → 缓冲区从头填满
- 旧连接的
omem内存不会秒释放,可能滞留数十秒;新连接又开始分配 → “踢一个、来两个、积三倍” - 结果是
used_memory_rss比used_memory高出 2 倍以上,瞬时内存尖峰直接 OOM - 集群中还会放大:一个节点抖动 → 多个客户端重连 → 其他节点缓冲区也跟着涨
调整 client-output-buffer-limit 的安全姿势
硬限、软限、超时时间必须配合,不能只加数字:
-
pub/sub场景:先观察峰值omem(比如稳定在 12MB),设为pubsub 64mb 16mb 120—— 给足余量,延长软限时间 -
normal场景(如 pipeline 或 monitor):避免用0 0 0,推荐normal 512mb 128mb 60—— 允许突发,但连续 60 秒超 128MB 就断 -
slave场景:RDB 2GB、带宽 20MB/s → 传输至少需 100 秒,time参数必须 ≥ 120;软限建议设为 RDB 大小的 1.5 倍(如 3GB) - 改完务必同步写入
redis.conf,否则重启后恢复默认值
缓冲区调大只是兜底,真正要查的是客户端有没有正确释放连接、复用是否混乱、消费逻辑是否阻塞 —— 这些不解决,再大的缓冲区也撑不了几天。


















