上一篇看到 Pub/Sub 会丢消息;Stream 则会保留。这篇不再重复「丢不丢」,而是把两者放在同一台实例上,量四个维度:离线补读、内存占用、发布方的代价、分发语义。选哪个,取决于这些数字回答的问题对你重不重要。
Pub/Sub:3 个订阅者上线后 0.2 秒内,0 个收到了东西(离线期间的 100 条不会补发) Stream:消费组上线后 XREADGROUP 一次读到 100 条(全部积压)
同样的 100 条,同时用 PUBLISH 和 XADD 各发一份。三个 Pub/Sub 订阅者上线后没有任何一个收到东西;Stream 的消费组一次 XREADGROUP 就拿回 100 条。
PUBLISH 10 万条(无订阅者):used_memory 变化 +28592 B XADD 10 万条:used_memory 变化 +11447584 B (114.5 B/条)
发布 10 万条(每条 100 字节)无订阅者的 PUBLISH,used_memory 只变了 +28592 字节(测量噪声);XADD 同样数量增加了 11447584 字节。Stream 必须自己控制长度(MAXLEN / XTRIM,见第 47 篇)。
订阅者数 N PUBLISH 中位 XADD 中位(对照)
0 27.1 µs 29.1 µs (PUBSUB NUMSUB = 0)
10 58.1 µs 29.3 µs (PUBSUB NUMSUB = 10)
100 375.3 µs 30.0 µs (PUBSUB NUMSUB = 100)
1000 3539.0 µs 29.1 µs (PUBSUB NUMSUB = 1000)
5000 17668.7 µs 29.3 µs (PUBSUB NUMSUB = 5000)订阅者放在另一个进程里持续排空,避免测量进程被拖慢。0 个订阅者时 PUBLISH 和 XADD 一样快(27 µs vs 29 µs);之后 PUBLISH 随订阅者数线性增加,约每个订阅者 3.5 µs,5000 个订阅者时一条 PUBLISH 要 17.7 ms;XADD 恒定在 29 µs 左右。PUBLISH 是在主线程里同步地向所有订阅者的输出缓冲区写数据——这点由耗时的线性增长间接印证,我没有做更细的剖析。
Pub/Sub 3 个订阅者: ['m1', 'm1', 'm1'] Stream 同组 3 个消费者: ['m1', None, None]
Pub/Sub 的一条消息被广播给所有订阅者;Stream 在同一个消费组里只交给一个消费者,不同的组才各得一份(第 41 篇)。所以「多个服务都要收到」用多个消费组,「多个实例分担」用同一个组。