Redis Pub/Sub性能随订阅者数量线性下降的根本原因是主线程对每条消息需为每个订阅者同步执行内存拷贝和socket写入,属O(N)硬伤;订阅者越多,output_buffer积压越严重,易触发断连与主线程阻塞。

Redis Pub/Sub 性能随订阅者数量线性下降的根本原因
不是网络或配置问题,而是 Redis 主线程必须为每条消息、每个订阅者单独执行一次内存拷贝 + socket 写入。订阅者从 1 个涨到 100 个,PUBLISH 的开销就接近翻 100 倍——这是 O(N) 时间复杂度的硬伤,无法靠调优绕过。
每次 PUBLISH 都在干这三件事
你调一次 PUBLISH channel "hello",Redis 主线程实际要完成:
- 查频道字典,拿到所有订阅该 channel 的客户端链表(O(1))
- 遍历链表,对每个客户端:把消息序列化后复制进其
output_buffer(O(N) 核心瓶颈) - 触发事件循环,尝试将 buffer 内容刷到 socket(若客户端卡住,buffer 积压,后续复制更慢)
注意:这个复制过程完全在主线程同步完成,不走 IO 线程,也不支持并行。哪怕你开了 io-threads 4,used_cpu_user 依然飙升。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
订阅者越多,缓冲区越容易失控
当某个订阅者处理慢或网络抖动,它的 client-output-buffer-limit pubsub 就会持续增长。一旦触发限制(默认 32MB 或 60 秒内超 8MB),Redis 强制断连——但断连前的积压已把主线程拖垮。
-
redis-cli info clients中client_longest_output_list > 1000是明确信号 -
redis-cli info memory中mem_clients_pubsub占比突增,说明大量内存被卡在输出缓冲区 - 用
CLIENT LIST查看,会发现很多连接的omem值稳定在几 MB 甚至更高
为什么加机器/加订阅进程反而恶化问题
Pub/Sub 是广播,不是队列。起 10 个 SUBSCRIBE 进程,等于让 Redis 把同一条消息复制 10 份、写 10 次 socket、占 10 倍 buffer 内存。
- 连接数线性涨 → 文件描述符耗尽风险 ↑
- 频道匹配开销也涨:内部用跳表存频道名,频道数爆炸时
PUBLISH前的模式匹配变慢 - Redisson 等客户端默认重连策略(如
EqualJitterDelay)在批量断连时可能引发雪崩式重连,瞬间打满连接数
真正卡点从来不在“能不能发”,而在“发完要不要等每个接收方确认”——而 Pub/Sub 的设计就是不等。


















