负载均衡分两块儿,一个是producer的负载均衡,一个是Comsumer的负载均衡

Producer负载均衡

Producer发送消息时,默认会轮询目标Topic下的所有MessageQueue,并采用递增取模的方式往不同的MessageQueue上发送消息,以达到让消息平均落在不同的queue上的目的。而由于MessageQueue是分布在不同的Broker上的,所以消息也会发送到不同的broker上。

RocketMQ生产者和消费者的负载均衡分配策略 - 图1

同时生产者在发送消息时,可以指定一个MessageQueueSelector。通过这个对象来将消息发送到自己指定的MessageQueue上,比如说只往MessageQueue4上面发, 这样可以保证消息局部有序。

Consumer负载均衡

Consumer也是以MessageQueue为单位来进行负载均衡。分为集群模式和广播模式。

1、集群模式

RocketMQ生产者和消费者的负载均衡分配策略 - 图2

一组Topic下的MessageQueue要把消息分发到不同的Comsumer,在同一个ConsumerGroup中, 一个消息如果你发给了Consumer1,就不能发送相同ConsumerGroup的别的Consumer上.

是怎么做到的呢?就是通过订阅的方式做到的,先根据集群的整个状况,把这些MessageQueue绑定到不同的Consumer上,比如说MessageQueue1和MessageQueue2绑定到Consumer1上, MessageQueue3和MessageQueue4 绑定到Consumer2上,

MessageQueue5和MessageQueue6绑定到Consumer3上.

那么Consumer1就会和MessageQueue1 MessageQueue2 建立一个长连接,那么MessageQueue1 MessageQueue2 的消息只能由Consumer1来消费.

同理Consumer2也会和MessageQueue3 MessageQueue4 建立一个长连接, MessageQueue3 MessageQueue4 的消息也只能由Consumer2来消费

这就是负载均衡机制

现在存在一个问题,就是我MessageQueue是通过什么样的配置分配到不同的Consumer的?,这就有文章了.

另外每当实例的数量有变更,都会触发一次所有实例的负载均衡,这时候会按照queue的数量和实例的数
量平均分配queue给每个实例。

每次分配时,都会将MessageQueue和消费者ID进行排序后,再用不同的分配算法进行分配。内置的分
配的算法共有六种,分别对应AllocateMessageQueueStrategy下的六种实现类,可以在consumer中
直接set来指定。默认情况下使用的是最简单的平均分配策略。

分配策略

  1. consumer.setAllocateMessageQueueStrategy("分配策略");

主要了解 AllocateMachineRoomNearby AllocateMessageQueueAveragely AllocateMessageQueueAveragelyByCircle 这三种,剩下的策略就用的不太多了.

AllocateMachineRoomNearby

AllocateMachineRoomNearby: 将同机房的Consumer和Broker优先分配在一起,这个策略就有用了,因为消费者和broker在一个机房里面,那么消费效率就很高了. 如果大型项目集群需要跨机房部署的时候就需要考虑这个策略了.

这个策略可以通过一个machineRoomResolver对象来定制Consumer和Broker的机房解析规则。然
后还需要引入另外一个分配策略来对同机房的Broker和Consumer进行分配。一般也就用简单的平均分
配策略或者轮询分配策略。

AllocateMessageQueueAveragely[默认策略]

AllocateMessageQueueAveragely:平均分配。将所有MessageQueue平均分给每一个消费者,

不设置策略的话,RocketMQ默认的策略就是这个策略.

RocketMQ生产者和消费者的负载均衡分配策略 - 图3

如果出现8个队列,三个消费者的话, 那么就两个消费者消费3个队列, 另外一个消费者消费2个队列,这个策略是尽量平均,不是绝对平均

AllocateMessageQueueAveragelyByCircle

AllocateMessageQueueAveragelyByCircle: 轮询分配。轮流的给一个消费者分配一个MessageQueue。

RocketMQ生产者和消费者的负载均衡分配策略 - 图4

AllocateMessageQueueByConfig

AllocateMessageQueueByConfig: 不分配,直接指定一个messageQueue列表。类似于广播模式,直接指定所有队列。

AllocateMessageQueueByMachineRoom

AllocateMessageQueueByMachineRoom:按逻辑机房的概念进行分配。又是对BrokerName和ConsumerIdc有定制化的配置。

AllocateMessageQueueConsistentHash

这个一致性哈希策略只需要指定一个虚拟节点数,是用的一个哈希环的算法,虚拟节点是为了让Hash数据在换上分布更为均匀。

RocketMQ生产者和消费者的负载均衡分配策略 - 图5

2、广播模式

广播模式下,每一条消息都会投递给订阅了Topic的所有消费者实例,所以也就没有消息分配这一说。而在实现上,就是在Consumer分配Queue时,所有Consumer都分到所有的Queue。

当消费负载均衡 consumer 和 queue 不对等的时候会发生什么

Consumer 和 queue 会优先平均分配,如果 Consumer 少于 queue 的个数,则会存在部分 Consumer 消费多个 queue 的情况,如果 Consumer 等于 queue 的个数,那就是一个 Consumer 消费一个 queue,如果 Consumer 个数大于 queue 的个数,那么会有部分Consumer 空余出来,白白的浪费了。