这是理论篇,实践篇参考【消息队列】MQ进阶篇之 RocketMQ 的实践
一、Apache RocketMQ 部署整体理解
RocketMQ 部署模型如上图所示,每个 Rocket 要有一个 NameServer 用来发现和管理 Broker,项目开发中使用 RocketMQ,也是要先配置 NameServer ,通过 NameServer 去找到存储信息的 Broker。每个Broker 都有一个master和一个或多个slave用来存储消息、收发消息。生产者向 broker 发消息,消费者从 broker 获取消息。
上图就是一个扩展后的消息模型,包括两个生产者,两个消息Topic,以及两组消费者 Comsumer。存储消息Topic的 代理服务器( Broker ),是实际部署过程对应的代理服务器。一个生产者可以生产多种话题的消息,一个话题下有多个Tag。为了方便生产消息的效率以及小范围的顺序性,出现了队列。一个话题的消息可以发给不同Broker上的队列。且一个队列可以对应多个消费组的消费者。一个消费者可以监听多个话题,也可以监听多个话题下的多个tag。
让我们用一个简单的比喻来解释这些概念:
.
生产者(Producer): 生产者就像是厨师,负责制作美味的菜品(消息)。他们将菜品送到厨房的出口(发送消息到消息队列)。
.
NameServer:NameServer是餐厅的前台,负责接待顾客(生产者和消费者)。它知道餐厅有哪些桌子(Broker),以及每个桌子的情况。
.
Broker: Broker就像餐厅的桌子,用于容纳顾客(消费者)和装菜品(消息)。有一个主桌(Master Broker)和几张副桌(Slave Broker)。
.
Master和Slave: Master就像主桌,负责接收和分发菜品。而Slave则是附属桌,用于备份和故障恢复,保证服务的可用性。
.
队列(Queue):队列就像是桌上的盘子,用于盛放不同的菜品(消息)。每个桌子(Broker)上都有多个盘子(队列),每个盘子里都可以装不同的菜品。
.
Topic: Topic就像是菜单,定义了餐厅提供的菜品种类。不同的Topic表示不同种类的消息。
.
Tag: Tag就像是菜品的分类,表示同一种Topic下的不同菜品种类。
.
消费组(Consumer Group):消费组就像是用餐的一群人,共同分享桌上的菜品。消费组中的每个人(消费者)都可以吃到相同的菜品,确保所有的人都能分到一份。
.
消费者(Consumer): 消费者就像是用餐的人,负责吃掉桌上的菜品(处理消息)。他们可以加入一个消费组,也可以单独用餐。
.
总体来说,生产者制作菜品,通过前台(NameServer)找到餐厅桌子(Broker),将菜品(消息)送到桌子上(队列)。消费者通过前台找到自己的桌子,享受美味的菜品(处理消息)。而Master和Slave的关系保证了即使有问题,餐厅也能继续提供服务。
二、Apache RocketMQ 部署架构关键部分详解
主要分为四部分:
1、生产者 Producer
发布消息的角色。Producer通过 MQ 的负载均衡模块选择相应的 Broker 集群队列进行消息投递,投递的过程支持快速失败和重试。
- 消息 RocketMQ 消息构成,Message 可以设置的属性值包括:如下图所示。
- Topic 与 Tag 都是业务上用来归类的标识,区别在于 Topic 是一级分类,而 Tag 可以理解为是二级分类。使用 Tag 可以实现对 Topic 中的消息进行过滤。Topic 和 Tag 的关系如下图所示。具体区别参考【消息队列】RocketMQ 消息的 topic 和 tag 区别以及使用方式
- 队列 为了支持高并发和水平扩展,需要对 Topic 进行分区,在 RocketMQ 中这被称为队列,一个 Topic 可能有多个队列,并且可能分布在不同的 Broker 上。
一般来说一条消息,如果没有重复发送(比如因为服务端没有响应而进行重试),则只会存在在 Topic 的其中一个队列中,消息在队列中按照先进先出的原则存储,每条消息会有自己的位点,每个队列会统计当前消息的总条数,这个称为最大位点 MaxOffset;队列的起始位置对应的位置叫做起始位点 MinOffset。队列可以提升消息发送和消费的并发度。
2、消费者 Consumer
消息消费的角色。在 Apache RocketMQ 中,消费者的概念涉及到一些重要的概念,包括消费组、消费位点、负载均衡以及消息推送和拉取。下面对这些概念进行简要介绍:
-
支持以推(push),拉(pull)两种模式对消息进行消费。
-
同时也支持集群方式和广播方式的消费。
-
提供实时消息订阅机制,可以满足大多数用户的需求。
-
消费组(Consumer Group):
- 在消费者中消费组的有非常重要的作用,如果多个消费者设置了相同的Consumer Group,我们认为这些消费者在同一个消费组内。
- 消费组(Consumer Group)是一组共享相同消费逻辑的消费者实例的集合。消费组的主要作用是协同处理消息,确保消息在消费者集合内得到分发,以达到负载均衡和容错的目的。
-
消费位点(Consumer Offset):
-
消费位点表示消费者在主题中的消费进度,即消费者已经成功消费的消息的位置。RocketMQ 使用消费位点来记录消费者的消费状态。
-
消费者在订阅主题时,可以选择从最早的消息开始消费(EARLIEST)或从最新的消息开始消费(LATEST)。
如上图所示,在Apache RocketMQ中每个队列都会记录自己的最小位点、最大位点。针对于消费组,还有消费位点的概念,在集群模式下,消费位点是由客户端提给交服务端保存的,在广播模式下,消费位点是由客户端自己保存的。一般情况下消费位点正常更新,不会出现消息重复,但如果消费者发生崩溃或有新的消费者加入群组,就会触发重平衡,重平衡完成后,每个消费者可能会分配到新的队列,而不是之前处理的队列。为了能继续之前的工作,消费者需要读取每个队列最后一次的提交的消费位点,然后从消费位点处继续拉取消息。但在实际执行过程中,由于客户端提交给服务端的消费位点并不是实时的,所以重平衡就可能会导致消息少量重复。 -
负载均衡:
消费者负载均衡是指消费者组内的多个消费者实例之间如何分配和协同处理消息。RocketMQ 提供了两种负载均衡算法:平均分配和加权分配。
- 平均分配是将消息均匀地分配给消费者组内的每个消费者实例。
- 加权分配则根据消费者实例的权重来分配消息,以实现不同消费者实例之间的不同处理能力。
-
消息推送和拉取:
- 消息推送是指消息 Broker 主动推送给消费者,消费者注册监听器,当有消息到达时触发回调。
- 消息拉取是指消费者主动从 Broker 拉取消息,可以根据需要控制拉取的频率和数量。
在 RocketMQ 中,消费者通过配置消费组和消费者实例名称来加入消费组。通过设置消费者的订阅信息和消费位点,可以控制消息的消费行为。负载均衡和消息推送/拉取方式的选择取决于具体的业务需求和性能要求。
总体而言,这些概念帮助构建了 RocketMQ 中的消息消费体系,使得消息能够被有效地分发和处理。
3、名字服务器 NameServer
NameServer(Name Server)是 RocketMQ 分布式架构中的一个关键组件。NameServer 的主要作用是管理整个 RocketMQ 集群的元数据信息,包括 T o p i c \color{Green}Topic Topic、 B r o k e r \color{Green}Broker Broker、 Q u e u e \color{Green}Queue Queue 等信息,最主要的是管理 Broker 和 路由信息。以下是 NameServer 的主要功能和作用:
- Broker 注册: 当一个 Broker 启动时,它会向 NameServer 注册自己的信息,包括 Broker 的名称、地址、版本等。NameServer 将这些信息保存下来,用于后续的路由查找。Broker 是存储消息Topic的 代理服务器,是实际部署过程对应的代理服务器。
- Topic 路由: 当生产者发送消息或消费者订阅消息时,NameServer 负责为相应的 Topic 提供路由信息。路由信息包括哪些 Broker 拥有该 Topic 的消息队列,以及这些队列的数量。每个NameServer将保存关于 Broker 集群的整个路由信息和用于客户端查询的队列信息。Producer和Consumer通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投