RocketMQ 集群消费与广播消费
-
消费组间广播消费:每个消费者分组只初始化唯一一个消费者,每个消费者可消费到消费者分组内所有的消息,各消费者分组都订阅相同的消息,以此实现单客户端级别的广播一对多推送效果。
该方式一般可用于网关推送、配置推送等场景。 -
消费组内共享消费(集群消费):,每个消费者分组下初始化了多个消费者,这些消费者共同分担消费者分组内的所有消息,实现消费者分组内流量的水平拆分和均衡负载。
该方式一般可用于微服务解耦场景。
一、概念详解
1. 集群消费(CLUSTERING)
- 定义:同一消费者组内的多个消费者共同消费队列消息,每条消息仅被组内的一个消费者处理。
- 特点:
- 负载均衡:队列在消费者间均匀分配,提高吞吐。
- 消息独占:队列级全局有序(若顺序消费),单条消息仅消费一次。
- 适用场景:大部分分布式系统场景,如订单处理、日志聚合。
2. 广播消费(BROADCASTING)
- 定义:同一消费者组内的每个消费者都会消费所有消息。
- 特点:
- 全量投递:每条消息被组内所有消费者处理。
- 无进度同步:消费进度由各消费者本地维护。
- 适用场景:配置推送、本地缓存刷新等需全量通知场景(安全性低,本地维护消费进度,不进行重试)。
3. 核心区别
维度 | 集群消费 | 广播消费 |
---|---|---|
消息分配 | 队列被消费者组均分 | 所有消费者消费全部队列 |
消费进度存储 | Broker 端(Remote) | 本地文件(Local) |
顺序性 | 队列内有序 | 无严格顺序 |
扩展性 | 高(水平扩展消费者) | 低(每个消费者全量处理) |
二、源码解析
1. 消费模式设置
消费者启动时指定消费模式,通过MessageModel
枚举控制:
// DefaultMQPushConsumer.java
public void setMessageModel(MessageModel messageModel) {
this.messageModel = messageModel;
}
2. 队列分配(Rebalance)
核心逻辑在RebalanceImpl
类中,根据消费模式分配队列:
集群模式分配
- 策略:使用
AllocateMessageQueueStrategy
(如平均分配策略)。 - 源码入口:
// RebalanceImpl.java public void doRebalance(boolean isOrder) { // 遍历订阅的Topic for (String topic : subscriptionInner.keySet()) { // 获取Topic下所有队列 Set<MessageQueue> mqSet = this.topicSubscribeInfoTable.get(topic); List<String> cidAll = this.mQClientFactory.findConsumerIdList(topic, consumerGroup); // 根据策略分配队列 AllocateMessageQueueStrategy strategy = this.allocateMessageQueueStrategy; List<MessageQueue> allocatedResult = strategy.allocate( this.consumerGroup, this.mQClientFactory.getClientId(), new ArrayList<>(mqSet), cidAll); // 更新分配结果 this.updateProcessQueueTableInRebalance(topic, allocatedResult, isOrder); } }
广播模式分配
- 策略:每个消费者获取全部队列。
// RebalanceBroadcast.java (继承自RebalanceImpl) @Override public void messageQueueChanged(String topic, Set<MessageQueue> mqAll, Set<MessageQueue> mqDivided) { // 直接分配所有队列给当前消费者 List<MessageQueue> allocatedResult = new ArrayList<>(mqAll); this.updateProcessQueueTableInRebalance(topic, allocatedResult, false); }
3. 消费进度管理
通过OffsetStore
接口实现,不同模式使用不同实现类:
-
集群模式:
RemoteBrokerOffsetStore
// 从Broker读取消费进度 long offset = this.fetchConsumeOffsetFromBroker(mq); // 定时提交进度到Broker this.updateConsumeOffsetToBroker(mq, offset);
-
广播模式:
LocalFileOffsetStore
// 从本地文件读取进度 long offset = this.readLocalOffset(mq); // 进度持久化到本地文件 this.writeLocalOffset(mq, offset);
4. 消息拉取与处理
-
拉取请求:由
PullMessageService
处理,根据分配的队列拉取消息。// PullMessageService.java public void run() { while (!this.isStopped()) { PullRequest pullRequest = this.pullRequestQueue.take(); this.pullMessage(pullRequest); } }
-
处理消息:
ConsumeMessageService
处理消息,区分并发/顺序消费。// ConsumeMessageConcurrentlyService.java public void submitConsumeRequest(List<MessageExt> msgs, ProcessQueue processQueue, MessageQueue messageQueue, boolean dispathToConsume) { ConsumeRequest consumeRequest = new ConsumeRequest(msgs, processQueue, messageQueue); this.consumeExecutor.submit(consumeRequest); }
-
提交进度:消费完成后提交进度。
// 集群模式提交到Broker this.offsetStore.updateOffset(mq, newOffset, false); // 广播模式写入本地文件 this.offsetStore.persist(mq);
5. 关键类图
DefaultMQPushConsumer
|-- DefaultMQPushConsumerImpl
|-- RebalanceService (触发Rebalance)
|-- RebalanceImpl (分配队列)
|-- AllocateMessageQueueStrategy (分配策略)
|-- PullAPIWrapper (拉取消息)
|-- OffsetStore (消费进度管理)
|-- RemoteBrokerOffsetStore (集群)
|-- LocalFileOffsetStore (广播)
|-- ConsumeMessageService (处理消息)
|-- ConsumeMessageConcurrentlyService
|-- ConsumeMessageOrderlyService
三、总结
- 集群消费:通过队列分配和远程进度存储实现负载均衡与消息独占。
- 广播消费:全量分配队列和本地进度管理确保消息全量投递。
- 源码关键点:
RebalanceImpl
的队列分配逻辑、OffsetStore
的差异化实现、消息拉取与处理流程。