负载均衡分两块儿,一个是producer的负载均衡,一个是Comsumer的负载均衡
Producer负载均衡
Producer发送消息时,默认会轮询目标Topic下的所有MessageQueue,并采用递增取模的方式往不同的MessageQueue上发送消息,以达到让消息平均落在不同的queue上的目的。而由于MessageQueue是分布在不同的Broker上的,所以消息也会发送到不同的broker上。
同时生产者在发送消息时,可以指定一个MessageQueueSelector。通过这个对象来将消息发送到自己指定的MessageQueue上,比如说只往MessageQueue4上面发, 这样可以保证消息局部有序。
Consumer负载均衡
Consumer也是以MessageQueue为单位来进行负载均衡。分为集群模式和广播模式。
1、集群模式
一组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来指定。默认情况下使用的是最简单的平均分配策略。
分配策略
consumer.setAllocateMessageQueueStrategy("分配策略");
主要了解 AllocateMachineRoomNearby AllocateMessageQueueAveragely AllocateMessageQueueAveragelyByCircle 这三种,剩下的策略就用的不太多了.
AllocateMachineRoomNearby
AllocateMachineRoomNearby: 将同机房的Consumer和Broker优先分配在一起,这个策略就有用了,因为消费者和broker在一个机房里面,那么消费效率就很高了. 如果大型项目集群需要跨机房部署的时候就需要考虑这个策略了.
这个策略可以通过一个machineRoomResolver对象来定制Consumer和Broker的机房解析规则。然
后还需要引入另外一个分配策略来对同机房的Broker和Consumer进行分配。一般也就用简单的平均分
配策略或者轮询分配策略。
AllocateMessageQueueAveragely[默认策略]
AllocateMessageQueueAveragely:平均分配。将所有MessageQueue平均分给每一个消费者,
不设置策略的话,RocketMQ默认的策略就是这个策略.
如果出现8个队列,三个消费者的话, 那么就两个消费者消费3个队列, 另外一个消费者消费2个队列,这个策略是尽量平均,不是绝对平均
AllocateMessageQueueAveragelyByCircle
AllocateMessageQueueAveragelyByCircle: 轮询分配。轮流的给一个消费者分配一个MessageQueue。
AllocateMessageQueueByConfig
AllocateMessageQueueByConfig: 不分配,直接指定一个messageQueue列表。类似于广播模式,直接指定所有队列。
AllocateMessageQueueByMachineRoom
AllocateMessageQueueByMachineRoom:按逻辑机房的概念进行分配。又是对BrokerName和ConsumerIdc有定制化的配置。
AllocateMessageQueueConsistentHash
这个一致性哈希策略只需要指定一个虚拟节点数,是用的一个哈希环的算法,虚拟节点是为了让Hash数据在换上分布更为均匀。
2、广播模式
广播模式下,每一条消息都会投递给订阅了Topic的所有消费者实例,所以也就没有消息分配这一说。而在实现上,就是在Consumer分配Queue时,所有Consumer都分到所有的Queue。
当消费负载均衡 consumer 和 queue 不对等的时候会发生什么
Consumer 和 queue 会优先平均分配,如果 Consumer 少于 queue 的个数,则会存在部分 Consumer 消费多个 queue 的情况,如果 Consumer 等于 queue 的个数,那就是一个 Consumer 消费一个 queue,如果 Consumer 个数大于 queue 的个数,那么会有部分Consumer 空余出来,白白的浪费了。