Skip to content

投递语义矩阵

本页结论:四个产品都能构建 at-least-once 链路,但手段不同——RabbitMQ 靠两段独立确认(Confirms + ACK),Kafka 靠 acks + offset 提交,RocketMQ 靠发送响应 + Broker 内置重投,Pulsar 靠 ack/negativeAck + 游标;exactly-once 只在有限边界内成立。

覆盖 spec §8.2 的矩阵:消息模型矩阵、路由矩阵、确认与投递矩阵、事务矩阵。版本基线与标记规则见矩阵总览(checkedAt: 2026-08-19)。

消息模型矩阵

能力RabbitMQKafkaRocketMQPulsar
竞争消费(工作队列)✅ 多消费者共享一个 Queue,prefetch 控制分发(routing✅ Consumer Group 内按分区分配(routing✅ 集群消费模式,组内分担 MessageQueue(routing✅ Shared/Failover 订阅分发到多消费者(routing
广播(发布订阅)✅ Fanout/Topic Exchange 一条消息复制到多 Queue(routing✅ 多个 Consumer Group 各自独立位点读全量日志(concepts✅ 广播消费模式或多 Consumer Group 各自消费(concepts✅ 同一 Topic 上建多个 Subscription,各自游标独立(concepts
分区日志模型➖ 队列无分区、ACK 即删,不是日志;RabbitMQ Streams 是例外但不在本仓库范围(storage-ha✅ 原生提交日志:追加写 + offset + retention(storage-ha✅ CommitLog 追加写 + MessageQueue 索引,消费不删(storage-ha✅ 分区 Topic + BookKeeper ledger,存算分离(storage-ha
请求-响应🔧 replyTo + correlationId 组合,x-direct-reply-to 免临时队列(routing🛠 自建 request/reply Topic + correlationId 关联(concepts🛠 自建请求/响应 Topic 关联;部分客户端版本提供 request/reply API(concepts🛠 自建请求/响应 Topic + correlationId 关联(concepts

路由矩阵

能力RabbitMQKafkaRocketMQPulsar
模式/内容路由✅ Direct/Topic/Fanout/Headers Exchange + Binding,Broker 端模式匹配(routing➖ 无 Broker 端模式路由;按 key 哈希到分区,内容过滤只能在消费端做(routing🔧 Tag 过滤为 Broker 端原生;SQL92 属性过滤需 Broker 开启配置(routing🧩 无 Exchange 概念;客户端支持按 Topic 模式(regex)订阅,Broker 端无模式路由(routing
Key 路由(决定顺序与负载)🔧 把业务 key 编入 routing key 绑定到固定队列,属约定而非机制(routing✅ partition key 哈希决定分区:同 key 同分区(routing✅ FIFO 消息的 MessageGroup 决定顺序组;普通消息按队列负载分发(routing✅ 分区 Topic 按 key 哈希;Key_Shared 订阅再按 key 绑定消费者(routing

确认与投递矩阵

能力RabbitMQKafkaRocketMQPulsar
生产确认✅ Publisher Confirms,异步等待 Broker 确认(reliability✅ acks 参数:0/1/all,acks=all 需 ISR 副本确认(reliability✅ 发送返回 SendResult(同步/异步/oneway 三种模式)(reliability✅ producer 收到 Broker ack;send 可异步(reliability
消费确认✅ 手动 basic.ack/nack;自动 ACK 模式等于不确认(reliability✅ offset 提交即确认;自动提交有丢失/重复窗口(reliability✅ PushConsumer 回调返回结果 / SimpleConsumer 显式 ack(reliability✅ individual/cumulative ack 推进游标(reliability
重投递✅ 未 ACK 的连接断开或 nack(requeue) 触发重新投递(reliability✅ 基于 offset 机制:消费者崩溃后从已提交位点重读(非 Broker 主动重投)(reliability✅ Broker 内置:消费失败自动进入重试队列重投(reliability✅ negativeAck 或 ack 超时触发 Broker 重投(reliability
生产端去重➖ 无 Broker 级消息去重,靠业务 messageId + 幂等(pitfalls✅ 幂等 Producer(enable.idempotence):PID+序列号去重,范围为单分区会话内(reliability🛠 Broker 不承诺全局去重,靠业务幂等表(pitfalls🛠 Broker 不做消费去重,靠业务幂等表(pitfalls
at-most-once✅ 自动 ACK + 不确认发布即可(牺牲可靠性换简单)(reliability✅ acks=0 + 自动提交位点(reliability✅ oneway 发送、失败不重发(reliability✅ 发送不等确认 + 自动 ack(reliability
at-least-once✅ Confirms + 持久化 + 手动 ACK 组合,业务必须预期重复(reliability✅ acks=all + 手动提交位点 + 幂等生产(reliability✅ 默认即 at-least-once:同步发送 + 内置重试重投(reliability✅ 手动 ack + 重投机制,业务必须预期重复(reliability
exactly-once➖ 无 Broker 级端到端 exactly-once;用幂等消费达成业务等效(reliability✅ 仅限 Kafka 内部:幂等 + 事务(EOS)覆盖 produce→process→produce 同一集群;写外部系统不成立(reliability➖ 无端到端 exactly-once;事务消息解决的是「发送与本地事务原子」(reliability➖ 消费端到端仍需幂等;事务提供的是跨分区原子操作而非外部系统 exactly-once(reliability

at-least-once 意味着业务必须预期重复,而不是「偶尔可能重复」:数据库提交成功、ACK 前崩溃就会重投。幂等消费基准实现见消费者崩溃与重投实验

事务矩阵

维度RabbitMQKafkaRocketMQPulsar
事务机制✅ channel 事务(txSelect/txCommit):把多条发布原子提交;性能差且不覆盖消费侧,生产多用 Publisher Confirms 替代(reliability✅ 事务 API:幂等 Producer + 多分区原子写 + 消费位点提交,消费端 read_committed 隔离(reliability✅ 事务消息:Half Message → 本地事务 → Commit/Rollback,状态不确定时 Broker 事务回查(reliability✅ Pulsar Transactions:跨 Topic/Partition 原子发送与 ack(reliability
原子边界仅「同一 channel 上多条发布要么都进 Broker 要么都不进」一次事务内的多分区写入 + offset 提交,边界在 Kafka 集群内「本地事务执行结果」与「消息最终投递/丢弃」二者原子一个事务内的跨分区/跨 Topic 写入与消费确认
涉及外部系统➖ 不包含任何业务副作用➖ 写外部数据库需 Outbox/幂等消费,EOS 不延伸出集群➖ 下游仍需可靠消费 + 幂等;回查只保证本地事务状态被最终确认➖ 外部副作用仍需业务协调
典型用途批量发布的原子性(少用)集群内 consume-transform-produce 管道「本地事务成功 ⇔ 消息一定投递」的最终一致场景跨分区原子写、流处理 Exactly-once 管道内部

脚注:同名异义

  • 「事务」:Kafka 事务是日志内原子多写 + EOS;RocketMQ 事务消息是「本地事务与消息发送的协调」(Half Message + 回查),不是分布式强一致事务;Pulsar 事务是跨分区原子操作;RabbitMQ channel 事务只是批量发布提交。四者都不等于跨数据库的分布式事务。
  • 「确认 / ACK」:RabbitMQ 的 ACK 是消息级逐条确认;Kafka 的「确认」是位点提交(批量、按分区);RocketMQ 的 ack 表示单条消费结果;Pulsar 的 ack 推进游标,cumulative ack 会一次性确认之前所有消息。「已确认」都不自动等于业务副作用绝对成功。
  • 「去重 / 幂等」:Kafka 幂等 Producer 只防「发送重试造成的分区内重复写入」,不防消费重复;消费去重在四个产品中都是业务责任。

相关页面

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