【六月更文打卡】RocketMQ面试题【续】

96 阅读3分钟

1、RocketMQ如何做负载均衡?

1)producer发送消息的负载均衡:默认会轮询向Topic的所有queue发送消息,以达到消息平均落到不同的queue上;而由于queue可以落在不同的broker上,就可以发到不同broker上(当然也可以指定发送到某个特定的queue上)

2)consumer订阅消息的负载均衡:假设有5个队列,两个消费者,则第一个消费者消费3个队列,第二个则消费2个队列,以达到平均消费的效果。而需要注意的是,当consumer的数量大于队列的数量的话,根据rocketMq的机制,多出来的Consumer 不会去消费数据,因此建议consumer的数量小于或者等于queue的数量,避免不必要的浪费

通过Topic在多Broker中分布式存储实现。

producer端
发送端指定message queue发送消息到相应的broker,来达到写入时的负载均衡

提升写入吞吐量,当多个producer同时向一个broker写入数据的时候,性能会下降
消息分布在多broker中,为负载消费做准备
默认策略是随机选择:

producer维护一个index
每次取节点会自增
index向所有broker个数取余
自带容错策略
其他实现:

SelectMessageQueueByHash
hash的是传入的args
SelectMessageQueueByRandom
SelectMessageQueueByMachineRoom 没有实现
也可以自定义实现MessageQueueSelector接口中的select方法

MessageQueue select(final List mqs, final Message msg, final Object arg);

consumer端
采用的是平均分配算法来进行负载均衡。

其他负载均衡算法

平均分配策略(默认)(AllocateMessageQueueAveragely) 环形分配策略(AllocateMessageQueueAveragelyByCircle) 手动配置分配策略(AllocateMessageQueueByConfig) 机房分配策略(AllocateMessageQueueByMachineRoom) 一致性哈希分配策略(AllocateMessageQueueConsistentHash) 靠近机房策略(AllocateMachineRoomNearby)

追问:当消费负载均衡consumer和queue不对等的时候会发生什么?
Consumer和queue会优先平均分配,如果Consumer少于queue的个数,则会存在部分Consumer消费多个queue的情况,如果Consumer等于queue的个数,那就是一个Consumer消费一个queue,如果Consumer个数大于queue的个数,那么会有部分Consumer空余出来,白白的浪费了。

2、消息重复消费

影响消息正常发送和消费的重要原因是网络的不确定性。

引起重复消费的原因

ACK
正常情况下在consumer真正消费完消息后应该发送ack,通知broker该消息已正常消费,从queue中剔除
当ack因为网络原因无法发送到broker,broker会认为此条消息没有被消费,此后会开启消息重投机制把消息再次投递到consumer

消费模式
在CLUSTERING模式下,消息在broker中会保证相同group的consumer消费一次,但是针对不同group的consumer会推送多次

解决方案
去重操作直接放在了消费端,消费端处理消息的业务逻辑保持幂等性。那么不管来多少条重复消息,可以实现处理的结果都一样。
数据库表
处理消息前,使用消息主键在表中带有约束的字段中insert。建立一张日志表,使用消息主键作为表的主键,在处理消息前,先insert表,再做消息处理。这样可以避免消息重复消费

Map
单机时可以使用map ConcurrentHashMap -> putIfAbsent guava cache

Redis
分布式锁搞起来。