RocketMQ核心面试题一次全给讲通透
文章目录
RocketMQ核心面试题,一次全给讲通透
--楼兰
RocketMQ的核心架构是什么样的?你项目当中是如何使用RocketMQ的?RocketMQ如何保证服务高可用?顺序消息、事务消息、延迟消息这些业务场景是怎么实现的?使用时如何对RocketMQ进行优化调优?这些都是RocketMQ的面试必考题。
如果你只是靠背面试题,那你会有背不完的面试题。听着别人说得头头是道,一到自己就磕磕绊绊。怎样才能让面试官真正相信你懂RocketMQ呢?如果你没有达到相声十级的水平,那么你需要的或许不是一些面试八股,而是一张思路清晰的架构设计图。理解了RocketMQ的核心设计,所有面试题都可以临场发挥。一图搞定所有面试题,RocketMQ走起!

这次我们通过一张架构图,带你彻底搞定RocketMQ的架构面试题,各种技术概念,各种使用技巧,从入门到精通,一次全搞定。
面设基础第一问:到底什么是MQ?有什么用?
我们先从一个场景开始:A服务需要远程调用B服务,A服务每秒发200个消息,B服务每秒只能处理100个。分分钟被压垮!
怎么办?加一层中间件——消息队列。A是生产者,B是消费者。

生产者发送的消息,在中间消息对列中排队,并分配一个编号。消费者按照自己的速度从消息对列中拉取消息进行消费,并记录自己的处理进度,称为offset偏移量。有了中间的消息对列做缓冲,B服务就能按照自己的速度处理消息。这样,一个消息对列也就成型了。
但问题马上就来了, 这只是个简陋的队列。面试官马上追问:“这和RocketMQ有什么关系?消费者多了,怎么提升性能?机器挂了,数据丢了怎么办?”
问到点子上了!“分步解决掉这些问题,RocketMQ就成型了。”
第一步:解决性能瓶颈
B处理不过来,消息会堆积。怎么办?很简单,多找几个业务相同的B组成一个消费者组 (Consumer Group) 一起干!

但问题又来了, 所有人都抢一个队列,还是有瓶颈!解决方案呢?有!给消息分类,就是主题(Topic)。一个Topic里再开多个队列(Queue)。生产者指定Topic发送消息,消息会均匀的写入到不同的对列当中。每个对列再去分配给消费者组当中的一个消费者进行消费。这样大家消费进度互不干涉,自然就能分工协作了。
这就好比超市结账,只开一个收银台肯定堵死。现在开了多个,每个消费者负责一个,效率瞬间起飞!
然后在消息对列的服务端,分别记录每个MessageQueue上的消息写入的进度,称为代理者位点。还有每个消费者组的消费进度,称为消费者位点。这样就可以有序的监控每个MessageQueue上消息的消费进度了。RocketMQ就是通过这些位点来监控消息的处理进度。

如果发生了消息堆积,也可以通过这些位点数据快速分析出来。
面试官紧接着问“那所有队列都在一台机器上,磁盘不就爆了吗?”
没错! 所以我们要搞Broker集群,实现水平扩展。由于每个MessageQueue都是独立管理自己的数据和消费进度,所以我们可以把一个Topic下的多个MessageQueue尽量均匀的分配到不同的Broker上,这样就减少了每个服务端的读写压力。
第二步:解决高可用
听到这里,面试官抛出了杀手锏:“你一个Broker机器挂了,上面的数据不就全没了吗?高可用怎么谈?”
这下就轮到,RocketMQ的主从架构 (Master/Slave)出场了。

每个主Broker(Master),都配一个从Broker(Slave)当“跟班”。
- Master 负责干活,处理读写。
- Slave 只负责一件事:拼命同步Master的数据。 Master挂了,Slave立刻顶上,变成新的Master。这就好比你喜欢的女生手机里,除了你,还得有个备胎。哦不,是备用联系人。这样就保证了服务不中断!
最核心的问题:谁来统一指挥?
接下俩面试官抛出了个灵魂问题:“生产者怎么知道该发给哪个Broker?消费者又该去哪拉消息?Broker挂了,主从切换了,它们怎么知道?”
这个问题,问的是整个集群的“大脑”。在RocketMQ中,这个大脑就是自主设计的NameServer了。

NameServer,就是RocketMQ的注册中心。它极其轻量,但干着最重要的事:
- 管户口:所有Broker都要向它报到,它知道谁活着。
- 管地图:它手里有张完整的路由表,知道每个Topic的队列在哪台机器上。
- 当向导:生产者和消费者都先问它要地图,然后才能找到正确的Broker通信。 为了保证向导自己不出事,NameServer自己也得是集群部署的!
终极拷问:你到底有没有做过设计?
最后,面试官问了个能区分“面霸”和“小白”的问题:“RocketMQ为什么要自主设计NameServer,而不直接使用Zookeeper这样的注册中心呢?”
这个问题,直击RocketMQ的设计哲学!
因为RocketMQ的核心是为金融、电商这类非常灵活的业务场景服务的,这使得RocketMQ的整个设计思路和Kafka这样极致追求吞吐量的消息中间件有根本上的区别。在保证高性能的同时,对于服务的可靠性要做到极致。
一方面,NameServer采用一种极为轻量级的集群方案。每个NameServer节点不需要与集群中的其他节点发生任何的数据交互。这样可以保证NameServer集群中,只要有任何一个节点正常工作,那么整个NameServer集群就能保持正常。
另一方面,业务的频繁更迭,使得RocketMQ也需要及时进行升级。自主研发的NameServer可以更灵活的应对新的业务场景。这使得RocketMQ可以很轻松的支持更复杂的服务端集群方案。例如支持自动选主的Dledger集群,支持选举和数据相分离的Raft集群。
#万剑归宗:RocketMQ你理解到哪一层了?
最后,有了RocketMQ的基础招式再加上终极设计哲学,RocketMQ的各种面试题,你就都有能力轻松应对了。
例如,面试官常问:为什么RocketMQ要设计生产者组,而Kafka中不需要呢?
这本质上还是因为RocketMQ的核心是为金融、电商这类严肃的业务场景服务的,而Kafka的核心则是为分布式日志这类对吞吐要求极高的业务场景服务的。在RocketMQ的业务场景下,事务消息是刚需。比如“下单”这个动作,需要保证生产者本地的“创建订单”和基于RocketMQ发送的“扣减库存”消息,要么都处理成功,要么都处理失败,不能有中间状态。
RocketMQ的Broker在处理这类事务时,需要反向回来检查生产者的状态。这时,生产者组的作用就来了,他告诉Broker:“我们是同一个业务的,你随便问我们组里任何一个人,都能知道这个事务最终是成功了还是失败了。“,如果某一个生产者实例崩溃了,Broker可以通过回查同一个生产者组内的其他实例来确定事务的最终状态。
这,就是ROcketMQ为了保证业务万无一失做的独特设计。
从一个简陋队列,层层递进,解决性能、高可用、集群协调,最后落地到核心业务。这就是一套为可靠业务而生的完整闭环。
理解到这,你就已经再是照搬RocketMQ各种API的小白了,而是一个真正懂RocketMQ设计哲学的高手了。
不管面试官再出什么面试题,你都可以从容应对了。
下面是一些常见的高阶面试题,答案在这里,自行理解。照着这些面试题准备面试,面试官也不得不夸你是真懂RocketMQ的。

最后留一个面试加分题:RocketMQ的消费者的Push模式在底层实际上是基于Pull模式的”长轮询“实现的。那什么是长轮询呢?RocketMQ又是如何针对长轮询进行优化的呢? 知道答案的同学,评论区见!答对的朋友,另有精细彩蛋。
