1、RocketMQ由哪些角色组成,每个角色作用和特点是什么?
角色 | 作用 |
NameServer | 无状态,动态列表;这也是和zookeeper 的重要区别之一。zookeeper 是有状态的。 |
Producer | 消息生产者,负责发消息到Broker 。 |
Broker | 就是MQ 本身,负责收发消息、持久化消息等。 |
Consumer | 消息消费者,负责从Broker 上拉去消息进行消费,消费完进行ack 。 |
2、RocketMQ
中的 Topic
和 JMS
的 queue
有什么区别?
答: queue
就是来源于数据结构的 FIFO
队列。而 Topic
是个抽象的概念,每个 Topic
底层对应N
个 queue
,而数据也真实存在 queue
上的。
3、RocketMQ Broker
中的消息被消费后会立即删除吗?
答: 不会,每条消息都会持久化到CommitLog
中,每个Consumer
连接到Broker
后会维持消费进度信息,当有消息消费后只是当前Consumer
的消费进度(CommitLog
的offset
)更新了。
4.6版本默认48小时后会删除不再使用的CommitLog
文件
- 检查这个文件最后访问时间
- 判断是否大于过期时间
- 指定时间删除,默认凌晨4点
4、RocketMQ
消费模式有几种
答: 消费模型由 Consumer
决定,消费维度为Topic
。
- 集群消费
- 一条消息只会被同
Group
中的一个Consumer
消费; - 多个
Group
同时消费一个Topic
时,每个Group
都会有一个Consumer
消费到数据;
- 一条消息只会被同
- 广播消费: 消息将对一 个
Consumer Group
下的各个Consumer
实例都消费一遍。即即使这些Consumer
属于同一个Consumer Group
,消息也会被Consumer Group
中的每个Consumer
都消费一次。
5、RocketMQ
消息是push
还是pull
答: RocketMQ
没有真正意义的push
,都是pull
,虽然有push
类,但实际底层实现采用的是 「长轮询机制」,即拉取方式。
6、为什么要主动拉取消息而不使用事件监听方式
答: 事件驱动方式是建立好长连接,由事件(发送数据)的方式来实时推送。
如果broker
主动推送消息的话有可能push
速度快,消费速度慢的情况,那么就会造成消息在 Consumer
端堆积过多,同时又不能被其他 Consumer
消费的情况。而 pull
的方式可以根据当前自身情况来 pull
,不会造成过多的压力而造成瓶颈。所以采取了 pull
的方式。
7、Broker
如何处理拉取请求的?
答: Consumer
首次请求Broker
,查询Broker
中是否有符合条件的消息
- 有
- 响应
Consumer
; - 等待下次
Consumer
的请求。
- 响应
- 没有
DefaultMessageStore#ReputMessageService#run
方法;PullRequestHoldService
来Hold
连接,每个5s
执行一次检查pullRequestTable
有没有消息,有的话立即推送;- 每隔
1ms
检查commitLog
中是否有新消息,有的话写入到pullRequestTable
; - 当有新消息的时候返回请求;
- 挂起
Consumer
的请求,即不断开连接,也不返回数据; - 使用
Consumer
的offset
。
8、RocketMQ
的负载均衡
通过Topic
在Brocker
中的分布式存储实现。
8.1、Producer
端
发送端指定 message queue
发送消息到相应的 broker
,来达到写入时的负载均衡
- 提升写入吞吐量,当多个
producer
同时向一个broker
写入数据的时候,性能会下降 - 消息分布在多
broker
中,为负载消费做准备
8.1.1、默认策略是随机选择
Producer
维护一个index
- 每次取节点会自增
index
向所有broker
个数取余- 自带容错策略
8.1.2、其他实现
SelectMessageQueueByHash
;Hash
的是传入的args
;SelectMessageQueueByRandom
;SelectMessageQueueByMachineRoom
没有实现。
8.1.3、自己实现 MessageQueueSelector
接口中的select
方法
MessageQueue select(final List<MessageQueue> mqs, final Message msg, final Object arg);
8.2、Consumer
端
默认采用的是平均分配算法来进行负载均衡。
8.2.1、其他负载均衡算法
- 平均分配策略(「默认」)(
AllocateMessageQueueAveragely
); - 环形分配策略(
AllocateMessageQueueAveragelyByCircle
); - 手动配置分配策略(
AllocateMessageQueueByConfig
); - 机房分配策略(
AllocateMessageQueueByMachineRoom
); - 一致性哈希分配策略(
AllocateMessageQueueConsistentHash
); - 靠近机房策略(
AllocateMachineRoomNearby
)。
9、当消费负载均衡 Consumer
和 queue
不对等的时候会发生什么?
Consumer
和 queue
会优先平均分配,如果 Consumer
少于 queue
的个数,则会存在部分 Consumer
消费多个 queue
的情况,如果 Consumer
等于 queue
的个数,那就是一个 Consumer
消费一个 queue
,如果 Consumer
个数大于 queue
的个数,那么会有部分 Consumer
空余出来,白白的浪费了。