Pub/Sub 与 Stream 的区别
Pub/Sub 是即发即忘的广播:消息发出后由当前在线订阅者接收,服务端不保存任何副本,订阅者掉线期间的消息永久消失。Stream 是有序、可持久化、带消费组的消息结构:每条消息有唯一 ID 并保存在服务端,消费组内竞争消费,未确认的消息留在待处理列表里可以重新投递。选择的关键不是「谁更快」,而是「消息丢了会怎样」。
基本信息
| Pub/Sub 命令 | SUBSCRIBE / PSUBSCRIBE 订阅,PUBLISH 发布,PUBSUB 查看状态 |
|---|---|
| Stream 命令 | XADD 写入,XREAD / XREADGROUP 读取,XACK 确认 |
| 持久化 | Pub/Sub 无,Stream 有(受 MAXLEN 与内存限制) |
| 分片广播 | 7.0 起支持 SSUBSCRIBE / SPUBLISH,把消息限定到槽所在分片 |
| 堆积表现 | Pub/Sub 客户端慢会被输出缓冲限制断开,Stream 由服务端存储承接 |
语义对比
| 维度 | Pub/Sub | Stream |
|---|---|---|
| 消息持久化 | 无,仅当时在线可收 | 持久保存,可按 ID 回溯 |
| 消费组 | 不支持,所有订阅者都收到同一份 | 支持,组内竞争消费、组间各消费一份 |
| 确认与重投 | 无 | PEL 加 XACK 加 XCLAIM 支持重投 |
| 顺序 | 按发布顺序推送,但无回溯能力 | 按 ID 严格有序,可指定起点重读 |
| 典型场景 | 配置广播、缓存失效通知、实时推送 | 订单事件、任务队列、审计日志 |
怎么选
- 只是通知「有变化」、订阅方丢了也无所谓,用 Pub/Sub,实现最简单且服务端不占内存
- 每条消息都必须被处理一次以上,选 Stream,用消费组与待处理列表保证不漏
- 需要按时间段回溯或按 ID 重放,选 Stream;Pub/Sub 完全没有历史
- 同一份消息要让多个业务方各消费一份,Stream 用多个消费组,Pub/Sub 用多个订阅频道
- 消息量极大且允许丢弃,用 Stream 加 MAXLEN 做近似保留,满额后自动淘汰最旧条目
两种写法对照
两种写法对照
redis-cli SUBSCRIBE config:updates # 订阅广播频道(会占用连接)
redis-cli PUBLISH config:updates reload # 发布,返回收到消息的订阅者数
redis-cli PUBSUB CHANNELS # 查看有订阅者的频道
redis-cli XADD events '*' type order-created id 1001 # 写入事件流
redis-cli XLEN events # 流内条目数
redis-cli XRANGE events - + COUNT 10 # 按 ID 区间读取集群下的广播范围:普通 Pub/Sub 在集群中是全局广播,消息会转发到所有节点;7.0 起的分片 Pub/Sub 把消息限制在槽所属分片,减少跨节点转发开销,订阅方需自行处理拓扑变化带来的重订阅。
把 Pub/Sub 当可靠队列使用是常见的线上事故来源:消费者重启或扩容期间订阅不存在,消息直接消失且没有任何痕迹。凡是「这条消息必须被处理」的场景,都应改用 Stream 或专业消息队列。