Skip to content

Apache Pulsar 订阅与分发

本页结论:Pulsar 的「分发」就是 Topic 订阅模型——广播靠多个订阅(各自独立 cursor、各收全量),竞争消费靠订阅内的 Shared/Key_Shared 分摊;分区 Topic 之上再叠加 key/轮转路由。它没有 Exchange/Binding,也没有 Kafka 式跨 Topic 消费组:Subscription 绑定单个 Topic,既是消费关系又是进度所有者。

适用场景

  • 一份数据多个下游:每个下游建一个订阅(审计、索引、通知各自全量)。
  • 任务型竞争消费:Shared 订阅内多消费者分摊(背压与积压)。
  • 同键有序 + 水平扩展:Key_Shared 按业务键粘连消费者。
  • 保序单消费/主备:Exclusive/Failover。

核心模型:Topic → Subscription → Consumer

  • 每个订阅持有独立 cursor:互不影响,互不竞争;删订阅不影响其他订阅。
  • 订阅类型在首个消费者连接时确定,决定该订阅内的分发语义。

四种订阅类型

类型分发语义顺序典型场景
Exclusive全量给唯一消费者;第二个消费者订阅同一订阅名立即冲突报错单分区内全序严格单消费者、保序处理
Failover主消费者收全量,备消费者 0 条;主断开后备接管单分区内全序保序 + 消费侧高可用
Shared消息在消费者间轮转分摊,无粘连不保证任何顺序竞争消费、吞吐优先的任务队列
Key_Shared同 key 消息粘连同一消费者;该消费者断开后 key 重新分配同 key 有序按实体分片的保序并行(如 orderId)

subscriptions 实验在同一 Topic(persistent://public/default/orders-subs)上依次验证四类:Exclusive 第二个消费者订阅即冲突;Shared 两个消费者各自收到 ≥1 条、合并去重后等于全量;Failover 主消费者收全量、备消费者 0 条,主退出后备接管新消息;Key_Shared 同 key 消息始终落在同一消费者:

bash
npm run lab -- pulsar subscriptions
快照待生成:运行 npm run lab -- pulsar subscriptions 后提交 outputs/pulsar/subscriptions.snapshot

分区 Topic 的 key 路由

  • 分区 Topic(partitioned topic)由 N 个非分区 Topic 组成;Producer 按 hash(key) % N 或轮转(无 key)把消息分布到各分区。
  • 顺序只在单分区内:同 key 进同分区才有局部顺序;「Pulsar Topic 没有分区概念」是禁止表述(见 陷阱)。
  • 订阅消费分区 Topic 时,四类订阅语义在每个分区上分别生效:如 Shared 订阅中每个分区的消息各自在消费者间分摊。
  • 分区数决定并行度上限(Shared/Key_Shared 的有效消费者数受分区数约束),且只能增不能减

与 Kafka 消费组、RabbitMQ 绑定的对照

关注点PulsarKafkaRabbitMQ
消费关系Subscription(绑定单个 Topic,携带 cursor)Consumer Group(可订阅多 Topic,携带 offset)Queue + Exchange Binding
广播多个订阅各收全量多个消费组各收全量fanout/topic exchange 绑多个队列
竞争消费同一订阅内 Shared/Key_Shared同一组内瓜分分区同一队列多消费者
key 的角色分区路由 + Key_Shared 粘连分区路由routing key 决定绑定匹配(路由到队列,不是分片)
进度的单位cursor(每订阅)offset(每组)逐条 ACK(队列删除)
拓扑选择时机订阅时选类型(四种语义)建 Topic 时定分区数声明 Exchange/Queue 时定类型

要点:Kafka 的「分发语义」由 Topic 分区 + 消费组固定(组内瓜分、组间广播);Pulsar 把选择权下放到每个订阅——同一 Topic 可以同时存在保序的 Exclusive 订阅和并行的 Shared 订阅。RabbitMQ 的路由发生在「进队列之前」(binding 匹配),Pulsar/Kafka 的路由发生在「写入时」(key→分区)与「消费时」(订阅类型)。

常见误区

  • 「Shared 订阅同 key 也有序」——不保证任何顺序;同键有序必须 Key_Shared(或单分区 + Exclusive/Failover),这是规格 §7.4 禁止表述(见 陷阱)。
  • 「多开消费者总能提速」——Exclusive/Failover 只有一个消费者干活;Shared/Key_Shared 受分区数与 key 分布约束,热点 key 会倾斜。
  • 「订阅名随便起、随时删」——cursor 与订阅名绑定;删订阅丢进度,同名重建从默认位置开始。
  • 「非分区 Topic 以后随时转分区」——形态转换需重建 Topic 并迁移生产/消费端,规划要趁早。

官方资料

以统一实验验证消息系统语义边界