文章目录
- 什么是消息队列?
- 消息队列的原理
- 消息队列工作原理
- RocketMQ 消息队列原理及工作机制
什么是消息队列?
- 队列是一种具有先进先出特点的数据结构,消息队列是基于队列实现的,存储具有特定格式的消息数据,比如定义一个包含消息类型、标志消息唯一性的 ID、消息内容的一个结构体作为消息数据的特定格式。消息以特定格式放入这个队列的尾部后可以直接返回,并不需要系统马上处理,之后会有其他进程从队列头部开始读取消息,按照消息放入的顺序逐一处理。引入消息队列的好处是,提高响应速度,以及实现组件间的解耦。
消息队列的原理
消息队列工作原理
- 消息队列的核心结构,如下图所示。与发布订阅模式类似,消息队列模式也是包括 3 个核心部分:
- 生产者。生产者会产生消息或数据,并将消息或数据插入到消息队列中。
- 消息队列。一种具有先进先出特点的数据结构,用于存储消息。
- 消费者。从消息队列中获取消息或数据,进行相关处理。
- 具体流程是,生产者将发送的消息插入消息队列,也就是入队,之后会有一个消费者从消息队列中逐次取出消息进行处理,完成出队。
RocketMQ 消息队列原理及工作机制
RocketMQ 的架构图
- RokcetMQ 共包括 NameServer Cluster、Producer Cluster、Broker Cluster 和 Consumer Cluster 共 4 部分。接下来,看看每部分的具体功能吧。
- NameServer Cluster,指的是名字服务器集群。这个集群的功能与 Kafka 中引入的 ZooKeeper 类似,提供分布式服务的协同和管理功能,在 RocketMQ 中主要是管理 Broker 的信息,包括有哪些 Broker、Broker 的地址和状态等,以方便生产者获取 Broker 信息发布消息,以及订阅者根据 Broker 信息获取消息。
- Producer Cluster,指的是生产者集群,负责接收用户数据,然后将数据发布到消息队列中心 Broker Cluster。那么,生产者按照集群的方式进行部署,好处可以概括为以下两点:
- 一是,多个 Producer 可以并发接收用户的输入数据,提升业务处理效率;
- 二是,考虑到可靠性问题,如果只有一个 Producer 接收用户输入数据,当这个 Producer 故障后,整个业务就无法运行了。
- Consumer Cluster,指的是消费者集群,负责从 Broker 中获取消息进行消费。Consumer 以集群方式进行部署的好处是,提升消费者的消费能力,以避免消息队列中心存储溢出,消息被丢弃。
- Broker Cluster,指的是 Broker 集群,负责存储 Producer Cluster 发布的数据,以方便消费者进行消费。 Broker Cluster 中的每个 Broker 都进行了主从设计,即每个 Broker 分为 Broker Master 和 Broker Slave,Master 既可以写又可以读,Slave 不可以写只可以读。每次 Broker Master 会把接收到的消息同步给 Broker Slave,以实现数据备份。一旦 Broker Master 崩溃了,就可以切换到 Broker Slave 继续提供服务。这种设计的好处是,提高了系统的可靠性。
Broker Cluster 的实现方式
- 在 Broker Cluster 中,消息的存储采用主题(Topic)+ 消息队列(Queue)的方式实现:
- 与 Kafka 一样,RocketMQ 中的主题也是一个逻辑概念。一个主题可以分区,分布在各个不同的 Broker 中,每个 Broker 上只有该主题的部分数据。每个主题分区中,队列的数量可以不同,由用户在创建主题时指定。队列是资源分配的基本单元,消息进行存储时会存放到相应主题的分区中。
RocketMQ 的工作流程
- 首先启动 NameServer,然后启动 Broker。Broker 启动后,会主动找 NameServer 建立连接,并将自己的信息注册到 NameServer 上。注册完毕后,Broker 会周期性地给 NameServer 发送心跳包,比如每隔 1s 发送一次,以告知 NameServer 自己还活着;心跳包里还可以包括 Broker 当前存储的数据信息,也就是说 Broker 可以周期性地向 NameServer 更新自己的数据信息,以保证 NameServer 上存储的数据是最新的。
- 创建主题,并确定这个主题的数据放入哪些 Broker 中。
- 当 Producer 生产消息发送到主题时,需要先到 NameServer 查询该主题存放在哪些 Broker 中,获取到相关 Broker 信息后,将消息发送给这些 Broker 进行存储。
- Consumer 要从主题消费消息,也需要首先到 NameServer 查询一下该主题的消息存储在哪些 Broker 上,然后去相应的 Broker 获取消息进行消费。
消息队列模式适用于什么场景
- 消息队列模式,是根据消费者需求到消息队列获取数据消费的,消费者只需要知道消息队列地址即可,消息队列中心也无需提前知道消费者信息。也就是说,这种模式对消费者没有特别需求,因此比较适合消费者为临时用户的场景。比如目前,阿里内部将 RocketMQ 应用于购物交易、充值、消息推送等多个场景,因为在这些场景下,每个消费者不是常驻进程或服务,几乎都是临时存在。此外,滴滴、联想等公司也都有采用 RocketMQ。
知识扩展:发布订阅和消息队列模式都支持系统解耦,两者是否一致呢?
概括地说,发布订阅和消息队列模式虽然都支持系统解耦,但它们在实现时采用的数据结构和方式并不相同。
首先,我们看一下它们实现解耦的数据结构。
发布订阅模式采用了消息中心,消息队列模式采用了消息队列中心,它们均用来存储生产者发布的数据,并均有主题、Broker 等概念;
唯一不同之处,是消息队列模式中采用了具有先进先出特征的队列结构进行存储,而订阅发布采用了 map 或数组等方式存储。
然后,我们再看看它们实现解耦的方式。
消息队列模式中,生产者发布数据到消息队列中心,消息队列中心会存储数据,等待消费者按需获取数据。这样生产者就不需要和消费者进行直接通信了,实现了生产者和消费者的解耦。
而在发布订阅模式中,消费者需要提前向消息中心订阅自己感兴趣的数据,待生产者发布数据到消息中心后,消息中心根据订阅者订阅信息将数据主动推送给消费者,也实现了消费者和生产者的解耦。
对于消息队列模式,消息队列中心无需提前获取消费者信息,因此对消费者比较灵活,适合消费者为临时用户的场景;而发布订阅模式,需要消费者提前向消息中心订阅消息,也就是说消息中心需要提前获取消费者信息,比较适合消费者为长驻进程或服务的场景。
你知道的越多,你不知道的越多。