redis pub/sub消息仅存于客户端输出缓冲区,不占用主数据内存且不计入used_memory;但缓冲区受client-output-buffer-limit限制,超限会断连,需配置maxmemory与合理策略保障稳定性。

Redis 发布订阅(Pub/Sub)本身不占用 Redis 主数据内存,但它的连接和消息缓冲区会受 maxmemory 限制间接影响——尤其是当启用 client-output-buffer-limit pubsub 且客户端消费滞后时。
Pub/Sub 消息到底存在哪?
Redis 的 Pub/Sub 是纯内存、无持久化的通信机制:消息只保留在客户端输出缓冲区中,不写入键空间,也不参与 maxmemory 统计。也就是说,INFO memory 里的 used_memory 不包含 Pub/Sub 消息体积。
但关键点在于:每个订阅客户端都维护一个独立的输出缓冲区(output buffer),用于暂存尚未被客户端读走的消息。这个缓冲区属于客户端连接资源,其大小受 client-output-buffer-limit 控制,而该限制一旦被突破,Redis 会强制断开连接——此时即使 maxmemory 远未达到,系统广播能力也会失效。
client-output-buffer-limit pubsub 怎么配才不掉线
默认配置是 client-output-buffer-limit pubsub 32mb 8mb 60,含义为:
- 硬限制 32MB:缓冲区超此值立即断连
- 软限制 8MB + 60秒:缓冲区持续 ≥8MB 超过 60 秒,也断连
生产环境中容易踩的坑:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- WebSocket 集群广播场景下,若某个后端实例临时宕机或网络抖动,对应客户端缓冲区会持续堆积,很快触发断连
- 把
pubsub缓冲区调得过大(如设成512mb),虽避免断连,但可能耗尽系统内存——因为这部分内存不计入used_memory,不会触发maxmemory-policy回收,却真实占物理内存 - 误以为“没设
maxmemory就没事”,其实缓冲区膨胀照样 OOM,只是错误不表现为OOM command not allowed when used memory > 'maxmemory',而是Client closed connection due to output buffer limit reached
为什么必须配 maxmemory 才能用好 Pub/Sub
看似 Pub/Sub 不走键空间,但实际依赖整个 Redis 实例的稳定性。没有 maxmemory,以下问题会放大:
- BGSAVE 或 AOF rewrite 时 fork 大内存进程失败,导致 RDB/AOF 中断,间接影响发布订阅服务的可靠性(例如主从切换失败)
- 大量订阅客户端连接 + 其他业务键写入,若无内存上限,OS 可能直接 OOM killer 干掉 redis-server 进程
-
maxmemory-policy虽不清理 Pub/Sub 缓冲区,但能防止普通键膨胀挤占系统资源,为订阅连接留出稳定运行空间
所以生产环境必须显式设置:maxmemory 4gb(按机器总内存 70% 分配),并搭配 maxmemory-policy allkeys-lru 或 volatile-lru,否则 Pub/Sub 的高可用就是空中楼阁。
监控 Pub/Sub 缓冲区是否健康
不能只看 used_memory,要主动检查缓冲区压力:
- 用
CLIENT LIST查看每个 client 的omem字段(单位字节),筛选出omem > 5_000_000的订阅连接 - 用
INFO clients关注client_longest_output_list和client_biggest_input_buf,这两个值持续升高是消费滞后的明确信号 - 在 Prometheus + Redis Exporter 中,重点关注
redis_clients_output_buffer_bytes{client_type="pubsub"}分位数曲线
缓冲区问题往往静默发生,等业务报“消息收不到”再查,通常已错过黄金处理窗口。真正难的不是配参数,而是把 omem 纳入日常巡检项——它不像键内存那样被 maxmemory 管着,却一样致命。










