每隔20秒就进行一下doRebalance;遍历订阅信息,对每个topic的队列进行重新负载
广播模式下,根据topic更新messageQueue
集群模式下,会使用负载均衡的策略,分配消费队列
1.机房就近
2.平均分配
3.平均轮询分配
4.根据配置分配
5.根据机房分配
6.一致性hash
然后根据分配结果,发生变更的话,就更新消费队列
1.CONSUME_FROM_LAST_OFFSET : 从队列最新偏移量开始消费
2.CONSUME_FROM_FIRST_OFFSET : 从队列头开始消费
3.CONSUME_FROM_TIMESTAMP : 从消费者启动的时间戳对应的消费进度开始消费
下面重点分步骤来详细探究 MQClientInstance.doRebalance 方法的执行流程。
2.1.1 MQClientInstance.doRebalance
1、根据 topic 来进行负载。
2、移除 MessageQueue,如果 MesageQueue 的 topic 不在订阅的主题中,接下来重点关注 rebalanceByTopic 方法。
RebalanceImpl rebalanceByTopic详解:
part1:根据消息消费模式(集群还是广播)我们先重点看集群模式。
part2: 获取主题的消息消费队列、主题与该消费组的消费者id列表,任意一个为空,则退出方法的执行。
part3: 主要是对主题的消息队列排序、消费者ID进行排序,然后利用分配算法,计算当前消费者ID(mqClient.clientId) 分配出需要拉取的消息队列。
part4: 更新主题的消息消费处理队列,并返回消息队列负载是否改变。
目前只看非顺序消息,逻辑就比较简单了,丢弃之前,先将 MessageQueue 消息消费进度 持久化,然后丢弃,重新被其他消费者加载。顺序消息将会本系列的后续文章中详细介绍。
接下来处理 MessageQueue 的 ProcessQueue,也就是在 ProcessQueueTable 中没有 mq 的处理队列(因为重新负载后,可能会分配一些新的队列)。