首页/数据/Redis 进阶速查/Pub/Sub 与 Stream:消息语义对比
数据结构与选型42 条

Pub/Sub 与 Stream:消息语义对比

Pub/Sub 是即发即忘的广播,订阅者掉线消息即丢;Stream 持久化每条消息、支持消费组与确认重投,二者按可靠性要求选择。

Redis 进阶速查数据更新于 2026-10-13

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/SubStream
消息持久化无,仅当时在线可收持久保存,可按 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 或专业消息队列。

易错点

  • 用 Pub/Sub 承载订单、支付这类不能丢的事件,消费者一次重启就造成消息永久缺失,且事后无法从 Redis 侧补回
  • 订阅连接被当成普通连接放进连接池或加了超时,一旦被回收或超时关闭,订阅静默失效
  • Stream 消费组不执行 XACK,待处理列表持续增长占用内存,需要用 XPENDING 监控并处理积压
  • Stream 不设置 MAXLEN 或 MINID,条目无限累积最终耗尽内存,写入方应在 XADD 时直接带上裁剪参数

数据来源与参考

  • Redis 官方文档:Pub/Sub 与 Streams 数据类型
  • Redis 7.0 Release Notes:Sharded Pub/Sub
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌