Kafka 消息生产与消费流程
1. 消息生产
-
生产者创建消息:
- 指定目标 Topic、Key(可选)、Value。
- 可附加 Header 信息(如时间戳、自定义元数据)。
-
选择分区(Partition):
- 若指定 Key,按 Key 的哈希值分配到对应 Partition。
- 若未指定 Key,按轮询或粘性分区策略分配。
-
发送消息到 Broker:
- 生产者将消息发送至对应 Partition 的 Leader Broker。
- 同步或异步发送,通过
acks
配置确认机制:acks=0
:不等待确认(可能丢失消息)。acks=1
:等待 Leader 写入成功。acks=all
:等待 Leader 和所有 ISR(In-Sync Replicas)副本写入成功。
-
Broker 持久化消息:
- Leader Broker 将消息追加到 Partition 的日志文件(顺序写入)。
- Follower Brokers 从 Leader 拉取消息进行副本同步。
2. 消息消费
-
消费者组订阅 Topic:
- 消费者组(Consumer Group)内的每个消费者分配到一个或多个 Partition。
- 每个 Partition 只能被组内的一个消费者消费。
-
拉取消息(Pull 模式):
- 消费者定期向 Broker 发送拉取请求,指定 Topic、Partition 及 Offset。
- 消费者维护当前消费的 Offset(可存储在 Kafka 内部 Topic 或外部系统)。
-
处理消息:
- 消费者处理消息后提交 Offset(自动或手动提交)。
- 若处理失败,可选择重试或跳过(需业务逻辑处理)。
-
分区再平衡(Rebalance):
- 消费者加入或离开时,触发 Rebalance,重新分配 Partition。
- 通过 Kafka 的 Coordinator(内部组件)管理消费者组状态。
RocketMQ 消息生产与消费流程
1. 消息生产
-
生产者创建消息:
- 指定目标 Topic、Tag(过滤标签)、Key(唯一标识)、Body。
- 可设置事务标识(用于事务消息)。
-
选择消息队列(MessageQueue):
- Topic 下分为多个 MessageQueue(默认 4 个)。
- 生产者按轮询、哈希或手动选择策略发送到某个 MessageQueue。
-
发送消息到 Broker:
- 消息发送至对应的 Broker Master 节点。
- 支持同步、异步、单向(Oneway)发送:
- 同步发送:等待 Broker 返回写入结果。
- 异步发送:通过回调处理结果。
- 单向发送:不等待响应(可能丢失消息)。
-
Broker 持久化消息:
- Broker 将消息写入 CommitLog(全局顺序写入的日志文件)。
- 异步构建 ConsumeQueue(消费队列索引)和 IndexFile(消息检索索引)。
2. 消息消费
-
消费者组订阅 Topic:
- 消费者组(Consumer Group)可设置为集群模式(消息负载均衡)或广播模式(全量广播)。
- 每个 MessageQueue 在同一时刻只能被组内的一个消费者消费。
-
拉取消息(Pull 模式):
- 消费者从 Broker 拉取消息,指定 Topic、MessageQueue 及消费位点(Offset)。
- RocketMQ 支持长轮询(Long Polling)减少无效请求。
-
处理消息:
- 消费者处理消息后返回消费状态(
CONSUME_SUCCESS
或RECONSUME_LATER
)。 - 若消费失败,消息进入重试队列(Retry Topic),最多重试 16 次后进入死信队列(DLQ)。
- 消费者处理消息后返回消费状态(
-
位点管理:
- 消费位点存储在 Broker(集群模式)或本地(广播模式)。
- 支持从指定时间点开始消费(如回溯历史消息)。
Kafka vs RocketMQ 核心差异
维度 | Kafka | RocketMQ |
---|---|---|
设计目标 | 高吞吐、日志流处理 | 高可靠、事务消息、顺序消息 |
存储模型 | Partition 日志文件,每个 Partition 独立存储 | CommitLog 统一存储,异步构建消费队列索引 |
消息确认机制 | 基于 acks 参数控制副本同步 |
支持同步/异步刷盘,主从同步复制 |
事务支持 | 有限支持(需配合外部事务) | 原生支持分布式事务消息(2PC) |
消息重试 | 需自行实现(如死信队列) | 内置重试队列和死信队列 |
消费模式 | 仅集群模式 | 支持集群模式和广播模式 |
运维复杂度 | 依赖 ZooKeeper,部署较复杂 | 依赖 NameServer,部署更轻量 |
1. 消息顺序性
Kafka
- 分区顺序性:Kafka通过分区(Partition)保证顺序。同一分区内的消息按写入顺序存储,消费者按顺序消费。
- 实现方式 :
- 生产者需将同一业务键(如订单ID)的消息发送到同一分区(通过指定Key哈希选择分区)。
- 消费者单线程消费同一分区(或使用
max.poll.records=1
避免并发)。
- 局限性:全局顺序需单分区,牺牲扩展性。
RocketMQ
- 队列顺序性:通过队列(Queue)实现顺序性,每个队列内消息有序。
- 实现方式 :
- 生产者使用
MessageQueueSelector
将同一业务标识的消息发送到同一队列。 - 消费者通过
MessageListenerOrderly
以加锁方式单线程消费队列。
- 生产者使用
- 支持模式:支持局部顺序(如订单操作)和严格全局顺序(需单队列,性能受限)。
对比
- 相似点:均依赖分区/队列的单线程处理。
- 差异:RocketMQ提供更显式的顺序消费API,Kafka需手动控制分区分配。
2. 消息不丢失
Kafka
- 生产者端 :
- 设置
acks=all
:等待所有ISR副本确认写入。 - 启用重试机制(
retries
)和幂等性(enable.idempotence=true
)。
- 设置
- Broker端 :
- 消息持久化到磁盘(可配置刷盘策略)。
- 多副本同步(ISR机制),
min.insync.replicas
确保最小存活副本数。
- 消费者端 :
- 手动提交偏移量(
enable.auto.commit=false
),处理完消息后提交。
- 手动提交偏移量(
RocketMQ
- 生产者端 :
- 同步发送(
sendSync
)等待Broker确认。 - 事务消息机制(两阶段提交)保障事务一致性。
- 同步发送(
- Broker端 :
- 同步刷盘(
flushDiskType=SYNC_FLUSH
)确保消息落盘。 - 主从复制(同步双写或异步复制)。
- 同步刷盘(
- 消费者端 :
- 消费者处理完成后手动ACK,失败时重试(重试队列+死信队列)。
对比
- 相似点:均依赖生产者确认、持久化、副本同步和消费者手动确认。
- 差异 :
- Kafka通过ISR动态管理副本,RocketMQ支持同步刷盘和事务消息。
- RocketMQ的重试队列机制更结构化,Kafka依赖消费者自行处理。
3. 高可用性
Kafka
- 副本机制 :
- 每个分区有多个副本,分布在不同Broker。
- Leader处理读写,Follower同步数据,Leader故障时从ISR选举新Leader。
- 控制器(Controller) :
- 负责分区Leader选举和集群状态管理。
- 依赖ZooKeeper :
- 存储元数据和Broker协调信息(未来版本将移除ZooKeeper依赖)。
RocketMQ
- 主从架构 :
- Broker分Master和Slave,Master处理写请求,Slave异步/同步复制数据。
- Master故障时,Slave可切换为Master(需手动或通过DLedger自动切换)。
- DLedger模式 :
- 基于Raft协议实现多副本一致性,自动选举Leader。
- Namesrv :
- 轻量级元数据管理服务(无强一致性依赖),Broker定期注册信息。
对比
- 相似点:均通过多副本和故障转移实现高可用。
- 差异 :
- Kafka依赖ZooKeeper协调,RocketMQ使用Namesrv和DLedger。
- RocketMQ的DLedger提供强一致性的自动选主,Kafka的ISR更侧重可用性。
总结
特性 | Kafka | RocketMQ |
---|---|---|
顺序性 | 分区内有序,依赖Key选择分区。 | 队列内有序,显式选择队列和顺序监听器。 |
消息不丢失 | ISR副本同步、生产者ACK、手动提交偏移。 | 同步刷盘、事务消息、主从复制。 |
高可用 | 多副本+ZooKeeper协调。 | 主从+DLedger自动选主+Namesrv。 |
适用场景
-
Kafka :
适合日志采集、流数据处理、实时分析等高吞吐场景,如 ELK 日志系统、用户行为追踪。
-
RocketMQ :
适合金融交易、订单处理、消息重试等高可靠性场景,如电商订单状态同步、支付事务消息。
总结
- Kafka 以吞吐量和水平扩展见长,适合大数据流式处理。
- RocketMQ 以事务消息和可靠性为核心,适合企业级复杂业务场景。
- 选择时需根据业务需求(吞吐量、可靠性、事务支持)及运维成本综合评估。