redis 6.0 的 pub/sub 消息分发仍由主线程单线程处理,多线程 io 仅加速网络读写,不提升广播性能;高扇出场景下易丢消息、延迟毛刺,应关闭 io-threads 并调优 buffer 与 hz 参数。

Redis 6.0 的 pub/sub 还是单线程处理,多线程 IO 不加速消息分发
直接说结论:Redis 6.0 引入的多线程 IO(由 io-threads 配置控制)**不参与 PUBLISH 消息的路由与分发逻辑**,只负责网络读写(read/write 系统调用层面)。SUBSCRIBE 客户端的消息广播仍由主线程串行执行——这意味着订阅者越多、频道越热,主线程在遍历客户端列表+序列化+写 socket 上的开销越大,吞吐瓶颈仍在主线程。
常见误判现象:redis-benchmark -r 10000 -n 100000 -P 50 -t publish 测试显示 QPS 提升,但这只是因为多线程分摊了连接建立、命令解析前的 socket 接收压力,并非 pub/sub 核心路径变快。
io-threads 开启后反而可能降低 pub/sub 稳定性
当启用 io-threads(如设为 4),主线程需与 IO 线程频繁同步客户端状态(比如某 client 断连,需通知所有 IO 线程清理其 socket 关联)。Pub/Sub 场景下大量短连接或频繁 UNSUBSCRIBE 会加剧这种同步开销,表现为:
-
latency doctor报出client-unlink或client-link延时毛刺 -
INFO clients中connected_clients波动剧烈,但client_longest_output_list持续升高 - 部分订阅者出现间歇性丢消息(非网络断开,而是主线程来不及 push 到 output buffer)
实操建议:纯 Pub/Sub 架构(如实时日志分发、IoT 设备广播)应关闭 io-threads(设为 1),并调大 client-output-buffer-limit pubsub,避免因缓冲区溢出触发强制 UNSUBSCRIBE。
真正影响 pub/sub 吞吐的三个配置项
比起多线程,以下参数对实际吞吐影响更直接:
-
client-output-buffer-limit pubsub 32mb 8mb 60:默认是8mb 2mb 60,高吞吐下极易触达硬限制导致 client 被踢;建议按峰值消息体积 × 订阅者数 × 秒级积压预估,宁大勿小 -
hz:默认 10,控制主线程每秒执行多少次常规任务(含 pubsub client 清理);设为 100 可加快积压 buffer 刷出,但增加 CPU 占用 -
tcp-keepalive:设为 300(秒)可更快感知异常断连,减少无效 client 占用输出缓冲区
注意:hz 超过 100 后边际收益极低,且可能干扰 EXPIRE 精度;线上环境建议 50–80 区间实测。
横向对比:为什么 Kafka / NATS 在高扇出场景更稳
Redis pub/sub 的本质是内存广播——每个 PUBLISH 都要复制 N 份消息体到 N 个 client output buffer。而 Kafka 是存储转发,NATS 使用共享内存+事件驱动分发。这意味着:
- 1000 订阅者发一条 1KB 消息,Redis 主线程至少做 1000×1KB 内存拷贝 + 1000 次 socket write 调度
- 同样场景下,NATS 的主线程只做一次序列化 + 一次内存引用分发
- Redis 没有消息确认、无重试、无持久化保证,一旦 client buffer 溢出即静默丢弃
如果业务需要可靠投递、高扇出(>500)、或消费者处理速度不均,别硬扛 Redis pub/sub——它不是为此设计的。用错地方时,调优 io-threads 只会掩盖架构问题。










