阿里巴巴 Rocket MQ 面试题

分布式消息队列可以提供应用解耦、流量消峰、消息分发、保证最终一致性、方便动态扩容等功能,已经成为大型互联网服务架构里标配的中间件。Rocket MQ 具有 单机吞吐量:十万级别,吞吐量高 时效性:ms级别 等特点,深受大家的喜爱!之前面试的过程中就遇到面试官问我你是如果使用Rocket MQ ,Rocket MQ 内部结构等等!如果之前不了解Rocket MQ ,看完这篇文章你会对 Rocket MQ 有一个很大的理解!如果你正在学习 Rocket MQ 一定要认真看完,真的很有用!推荐一本书 《Rocket MQ 实战与原理解析》

Rocket MQ 集群部署示意图
Rocket MQ 由四部分组成:Producer、Consumer、Broker和NameServer

1.NameServer是如何与Broker进行协调的?

每个broker启动都得向所有的NameServer进行注册,Broker会跟每个NameServer都建立一个TCP长连接,Broker会每隔30s给所有的NameServer发送心跳,告诉每个NameServer自己目前还活着,然后NameServer会每隔10s运行一个任务,去检查一个各个Broker的最近一次心跳时间,如果某个Broker超过120s都没发送心跳了,那么就认为这个Broker已经挂掉了。

2.Master Broker是如何将消息同步给Slave Broker的?

Rocket MQ 的Master-Slave模式采取的是Slave Broker不停的发送请求到Master Broker去拉取消息。采用的是Pull模式拉取消息。

3.作为消费者的系统再获取消息的时候,是从Master Broker获取消息,还是从Slave Broker获取消息?

作为消费者的系统在获取消息的时候会发送请求到Master Broker上去,请求获取一批消息,此时Master Broker是会返回一批消息给消费者系统,然后Master Broker在返回消息给消费者系统的时候,会根据当时Master Broker的负载情况和Slaver Broker的同步情况,向消费者系统建议下一次拉取消息的时候是从Master Broker拉取还是从Slave Broker拉取。

4.Rocket MQ 4.5版本后是如何实现Master Broker 与Slave Broker切换的?

Rocket MQ 4.5版本后支持了一种机制叫做 Dledger,是基于Raft协议实现的一个机制,一旦Master Broker宕机,既可以在多个Slave Broker中,通过Dledger技术和Raft协议算法进行leader选举,直接将一个Slave Broker选举为新的Master Broker。

5.Rocket MQ 对事务的支持

1)发送方向Rocket MQ 发送“待确认”消息(half消息)。
2)Rocket MQ 将收到的“待确认”消息持久化成功后,向发送方回复消息已经发送成功,此时第一阶段消息发送完成。
3)发送方开始执行本地事件逻辑。
4)发送方根据本地事件执行结果向Rocket MQ 发送二次确认(Commit或是Rollback)消息,Rocket MQ 收到Commit状态则将第一阶段消息标记为可投递,订阅方将能够收到该消息;收到Rollback状态则删除第一阶段的消息,订阅方接收不到该消息。
5)如果出现异常情况,步骤4)提交的二次确认最终未到达Rocket MQ ,服务器在经过固定时间段后将对“待确认”消息发起回查请求。
6)发送方收到消息回查请求后(如果发送一阶段消息的Producer不能工作,回查请求将被发送到和Producer在同一个Group里的其他Producer),通过检查对应消息的本地事件执行结果返回Commit或Rollback状态。

6.Rocket MQ 支持两种消息模式:Clustering和Broadcasting。

1.在Clustering模式下,同一个ConsumerGroup(GroupName相同)里的每个Consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消费的内容合起来才是所订阅Topic内容的整体,从而达到负载均衡的目的。
2.在Broadcasting模式下,同一个ConsumerGroup里的每个Consumer都能消费到所订阅Topic的全部消息,也就是一个消息会被多次分发,被多个Consumer消费。

7.Rocket MQ 保证消息不丢失,但有可能造成消息重复,你们业务是如果保证数据不重复消费的?

消息重复一般情况下不会发生,但是如果消息量大,网络有波动,消息重复就是个大概率事件。比如Producer有个函数setRetryTimesWhenSendFailed,设置在同步方式下自动重试的次数,默认值是2,这样当第一次发送消息时,Broker端接收到了消息但是没有正确返回发送成功的状态,就造成了消息重复。

解决消息重复有两种方法:第一种方法是保证消费逻辑的幂等性(多次调用和一次调用效果相同);另一种方法是维护一个已消费消息的记录,消费前查询这个消息是否被消费过。这两种方法都需要使用者自己实现。

8.Rocket MQ 的具体消息存储结构是怎样的呢?

Rocket MQ 消息的存储是由ConsumeQueue和CommitLog配合完成的,消息真正的物理存储文件是CommitLog,ConsumeQueue是消息的逻辑队列,类似数据库的索引文件,存储的是指向物理存储的地址。每个Topic下的每个Message Queue都有一个对应的ConsumeQueue文件

CommitLog以物理文件的方式存放,每台Broker上的CommitLog被本机器所有ConsumeQueue共享,在CommitLog中,一个消息的存储长度是不固定的,Rocket MQ 采取一些机制,尽量向CommitLog中顺序写,但是随机读。ConsumeQueue的内容也会被写到磁盘里作持久存储。

9.消息在通过Producer写入Rocket MQ 的时候,有两种写磁盘方式,同步刷新,异步刷新

1.异步刷盘方式:在返回写成功状态时,消息可能只是被写入了内存的PAGECACHE,写操作的返回快,吞吐量大;当内存里的消息量积累到一定程度时,统一触发写磁盘动作,快速写入。

2.同步刷盘方式:在返回写成功状态时,消息已经被写入磁盘。具体流程是,消息写入内存的PAGECACHE后,立刻通知刷盘线程刷盘,然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。