本章,我们先来看下RocketMQ的基本架构,涉及哪些核心组件,以及各个组件之间的关系又是怎样的。
一、基本架构
在RockectMQ中,一共有四个核心组件: NameServer 、 Broker 、 Producer 、 Customer ,它们之间的基本关系可以用RocketMQ官方的一张图表示:
上图中,Broker Cluster就是各个RocketMQ进程,Producer Cluster和Consumer Cluster分别是生产者和消费者,NameServer Cluster是路由中心。
看不懂?没关系,我们下面将一一分析上述的各个组件。
1.1 Broker
我们在每台机器上部署的RocketMQ进程,就称为 Broker 。 Broker主要负责消息的存储,一般来说,在一台配置好一点的机器上部署单个Broker实例后,可以抗大约10万QPS的请求。
我们可以看上图,Broker本身可以构建成一个集群,我们的所有消息数据是以数据分片的形式分布在各个Broker节点上,也就是每个Broker节点保存总数据的一部分。此外,为了保证集群的可用性,每个Broker节点都有自己的副本(Slave),它们之间会进行数据同步。
Broker集群的整个架构就是我们在分布式篇中讲过的数据分散集群架构和Master/Slave架构的结合。
1.2 NameServer
NameServer是RocketMQ的路由中心,每一个NameServer节点都保存着 全量 的路由信息。因为Broker是集群部署,所以当生产者发送消息时,需要知道将消息发送到哪个Broker,当消息者获取消息时,也需要知道从哪个Broker获取消息。
每一个Broker节点(包括Slave)都会通过 心跳机制 (TCP长连接),将自己的基本信息注册到每一个NameServer中,这样Producer和Consumer就可以从NameServer拉取到路由消息。
默认情况下,每个Broker会 每隔30s 给所有的NameServer发送心跳,告诉NameServer自己还活着;与此同时,每个NameServer 每隔10s 检查一下各个Broker的最近一次心跳时间,如果发现某个Broker 超过120s 都没发送心跳,就认为这个Broker已经挂掉了,会将其从路由信息里移除。
所谓的路由信息,可以理解为Broker集群里的各个Broker的自身信息。
1.3 Producer
生产者,用于生产消息,会 定时从NameServer拉取路由信息 ,然后根据路由信息与指定的Broker建立TCP长连接,从而将消息发送到Broker中。
1.4 Consumer
消费者,用于消费消息,会 定时从NameServer拉取路由信息 ,然后根据路由信息与指定的Broker建立TCP长连接,从而从Broker拉取消息。
二、高可用
了解完RocketMQ的基本架构后,我们先来看看RocketMQ是如何实现高可用的。由于Producer和Consumer是直接与我们的客户端程序相关的,可用性由我们自己来保证,所以重点看下NameServer和Broker。
2.1 NameServer的可用性
NameServer管理着Broker的基本信息,如果NameServer挂掉了,那么生产者和消费者就找不到Broker了,所以NameServer需要以集群方式部署来实现高可用。在RocketMQ中, 每个NameServer都保存着Broker集群的所有Broker信息 ,所以就算一台NameServer服务器宕机了,还有其它NameServer可用。
2.2 Broker的可用性
每个Broker节点都是主从架构,所以就算主节点宕掉了,从节点依然可以提供服务。但这里就要思考两个问题:
- 主从节点之间如何进行数据同步?
- RokectMQ是否具有故障自动转移机制(即主节点挂掉后,从节点自动成为主节点,不需要人工介入)?
对于第一点,每一个Slave-Broker节点都会去自己的Master节点那里拉取数据,以进行同步;
对于第二点,在RocketMQ4.5版本以前,如果Master节点挂掉了,需要手动选出一个Slave节点重新作为Master节点,效率很低。所以4.5版本后,RocketMQ引入了 Dleger机制 ,采用Raft协议进行主从节点的选举,实现故障自动转移。
关于Raft协议,读者可以参考我的《分布式系统从理论到实战系列》,我也会在进阶篇中对Dleger机制的原理做详细讲解。
三、可扩展
RocketMQ之所以具有可扩展性,是因为每个Broker节点只保存整体数据的一部分,这样当数据量越来越大时,可以进行水平切分。如果读者对RabbitMQ有所了解就知道,RabbitMQ中的每个节点保存着全量数据,那么当数据量越来越大时,是没法水平扩展的,而RocketMQ通过数据分散集群的模式实现了水平扩展。
3.1 Topic和Tag
在RocketMQ中,每一个消息都有其所属的 Topic ,所谓Topic,就是 数据集合 的意思,是一个逻辑概念。
举个例子,假设我们的订单系统需要往MQ里发送订单消息,那此时就应该建立一个Topic,它的名字可以叫做:topic_orderInfo,也就是一个包含了所有订单消息的数据集合。然后生产者发送消息时,就必须指定好消息所属的Topic,消费者消费消息时,也需要指定从哪个Topic里获取消息。
Broker在存储消息时,每一个Topic中的所有消息数据可能会分散在不同的Broker节点上,我们可以在创建Topic时进行指定。比如,假设我们的topic_orderInfo包含900万条消息,我们指定其分散在3个Broker节点上,那么每个节点就包含300万条消息数据:
除了Topic外,还有一个Tag分类,区分在于 Topic 是一级分类,而 Tag 可以理解为是二级分类。
那到底什么时候该用 Topic,什么时候该用 Tag?建议如下:
- 消息类型是否一致:如普通消息、事务消息、定时(延时)消息、顺序消息,不同的消息类型使用不同的 Topic,无法通过 Tag 进行区分;
- 业务是否相关联:没有直接关联的消息,如淘宝交易消息,京东物流消息使用不同的 Topic 进行区分;而同样是天猫交易消息,电器类订单、女装类订单、化妆品类订单的消息可以用 Tag 进行区分;
- 消息优先级是否一致:如同样是物流消息,盒马必须小时内送达,天猫超市 24 小时内送达,淘宝物流则相对会慢一些,不同优先级的消息用不同的 Topic 进行区分;
- 消息量级是否相当:有些业务消息虽然量小但是实时性要求高,如果跟某些万亿量级的消息使用同一个 Topic,则有可能会因为过长的等待时间而“饿死”,此时需要将不同量级的消息进行拆分,使用不同的 Topic。
每个Broker都通过心跳机制告诉NameServer:我这里有哪些类型的Topic,每类Topic的哪些数据保存在我这。所以生产者才会知道向哪个Broker发送消息,消费者同理。
另外要注意: 生产者只能往Master-Broker节点发送消息,消费既可以从Master-Broker节点消费消息,也可以从Slave-Broker节点消费消息 ,这个我们后面讲解Broker持久化原理时会详细介绍。
四、总结
本章,我们介绍了RocketMQ的基本架构,并对其中的 NameServer 、 Broker 、 Producer 、 Customer 这四个核心组件进行了简要讲解。RocketMQ实现高可用和可扩展的思路其实没什么新意,就是基于Raft协议的主从架构,以及数据分散集群模式。
如果读者对Spring Cloud有所了解,就会发现,RocketMQ的基本架构和Spring Cloud中的很多组件非常相似,比如 NameServer ,其实就是类似于Spring Cloud中的Eureka服务注册中心,读者也可以结合我的《分布式系统从理论到实战系列》进行比较。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。