目录
Name Server、Topic 和 Broker 之间的关系
前言
RocketMQ是一个分布式消息中间件,支持高性能、高可靠性的消息传输。理解RocketMQ的基本概念是深入学习和使用它的基础。以下是对RocketMQ消息队列基本概念的详细讲解。声明: 本文中部分内容来源于Apache RocketMQ官方社区
领域模型
Apache RocketMQ 是一款典型的分布式架构下的中间件产品,使用异步通信方式和发布订阅的消息传输模型。通信方式和传输模型的具体说明,请参见下文通信方式介绍和消息传输模型介绍。 Apache RocketMQ 产品具备异步通信的优势,系统拓扑简单、上下游耦合较弱,主要应用于异步解耦,流量削峰填谷等场景。
Apache RocketMQ领域模型
如上图所示,Apache RocketMQ 中消息的生命周期主要分为消息生产、消息存储、消息消费这三部分。
生产者生产消息并发送至 Apache RocketMQ 服务端,消息被存储在服务端的主题中,消费者通过订阅主题消费消息。
消息模型
RocketMQ支持两种主要的消息模型:点对点模型(P2P)和发布/订阅模型(Pub/Sub)。
1.1 点对点模型(P2P)
在点对点模型中,消息被发送到一个特定的**队列(Queue)**中,只有一个消费者能够消费这条消息。消息一旦被消费,就从队列中移除。
- 生产者(Producer):将消息发送到队列中。
- 消费者(Consumer):从队列中接收并处理消息。每条消息只会被一个消费者处理。
- 应用场景:任务调度系统、工作负载分配、分布式事务等。
特点:
- 消息有且仅有一个消费者会消费它,其他消费者不能看到这条消息。
- 消息一旦被消费就会被移除,因此不会重复消费。
1.2 发布/订阅模型(Pub/Sub)
在发布/订阅模型中,消息被发送到**主题(Topic)**中,所有订阅了该主题的消费者都能接收到这条消息。
- 生产者(Producer):将消息发布到主题中。
- 消费者(Consumer):订阅一个或多个主题,消费主题中的消息。每个消费者都能接收到所有发布到订阅主题的消息。
- 应用场景:广播消息、事件通知、日志收集等。
特点:
- 一条消息可以被多个消费者消费,适用于需要广播消息的场景。
- 订阅者可以随时订阅或取消订阅某个主题。
队列与主题的区别
2.1 队列(Queue)
队列是点对点模型中的核心概念,用于保存待处理的消息。队列中的消息遵循**FIFO(先进先出)**原则。
- 应用场景:处理需要保证严格顺序的任务,如事务性消息、任务调度等。
- 特点:每条消息只能被一个消费者消费,消息一旦消费即从队列中删除。
2.2 主题(Topic)
主题是发布/订阅模型中的核心概念,用于广播消息给多个订阅者。主题中的消息可以被多个消费者同时接收。
- 应用场景:系统事件广播、多点通知、实时数据推送等。
- 特点:消息可以被多个消费者同时消费,每个订阅者都会收到发布到主题中的所有消息。
生产者与消费者模式
3.1 生产者(Producer)
生产者是消息的发送方,负责将消息推送到指定的队列或主题。生产者在RocketMQ中可以使用多种发送模式:
- 同步发送:生产者发送消息后等待Broker确认消息已成功接收,适用于需要确保消息可靠发送的场景。
- 异步发送:生产者发送消息后不等待Broker确认,而是立即继续处理其他任务。适用于对消息发送速度要求高的场景。
- 单向发送:生产者只发送消息而不关心是否成功接收。适用于日志收集等不需要确认的场景。
3.2 消费者(Consumer)
消费者是消息的接收方,负责从队列或主题中拉取并处理消息。消费者在RocketMQ中可以使用不同的消费模式:
- 推(Push)模式:消息一到达队列或主题,立即推送给消费者。适用于需要实时处理的场景。
- 拉(Pull)模式:消费者定期主动从队列或主题中拉取消息进行处理。适用于控制消息处理频率或批量处理的场景。
消息的可靠性
4.1 持久化消息
RocketMQ支持消息的持久化,即将消息存储在磁盘中,以确保即使在系统崩溃或重启后,消息依然可用。
- 同步刷盘:生产者发送消息后,Broker立即将消息写入磁盘并返回确认。此模式确保了最高的消息可靠性,但也会影响性能。
- 异步刷盘:生产者发送消息后,Broker首先将消息写入内存,然后批量写入磁盘。此模式提高了性能,但在系统故障时可能会丢失部分消息。
4.2 消息确认机制
为了确保消息被成功消费,RocketMQ采用了ACK机制。消费者处理完消息后,需要向Broker发送确认(ACK),表明消息已成功处理。只有在收到ACK后,Broker才会将消息从队列中删除。
- 手动确认:消费者需要显式地调用ACK方法确认消息已处理完毕。
- 自动确认:消费者处理完消息后自动发送ACK,无需显式调用。
通信方式
5.1 同步通信
同步发送
同步发送是指生产者发送消息后,会等待Broker的确认响应(ACK)后才继续执行后续操作。这种通信方式适用于对消息传递可靠性要求高的场景。
优点:
- 高可靠性:生产者只有在接收到Broker的确认后才会认为消息发送成功。
- 易于处理失败:如果发送失败,可以在生产者端进行重试或记录日志。
缺点:
- 性能较低:生产者需要等待Broker的确认,因此每次发送消息的时间相对较长。
应用场景:
- 订单系统:在订单生成后,确保消息可靠地传递到Broker。
- 金融交易:确保交易消息不丢失且可靠送达。
5.2 异步通信
异步发送
异步发送是指生产者发送消息后,不等待Broker的确认响应,而是通过回调函数处理发送结果。这种通信方式适用于对性能要求高,但可以接受一定程度失败的场景。
优点:
- 高性能:生产者发送消息后立即返回,不需要等待Broker的确认,因此可以快速发送大量消息。
- 非阻塞:生产者线程不会因为等待消息确认而被阻塞。
缺点:
- 可靠性较低:由于不等待确认,可能会出现消息丢失的情况。
应用场景:
- 实时日志收集:对日志传递的可靠性要求不高,但要求高吞吐量。
- 流量控制:需要高效处理大量请求,但允许部分失败。
5.3 单向通信
单向发送
单向发送是指生产者只负责将消息发送给Broker,而不关心Broker是否接收到消息,也不要求Broker返回任何确认。这种方式适用于对性能要求极高且不关心消息是否真正送达的场景。
优点:
- 极高性能:生产者只发送消息,不等待任何响应,因此可以极高效地发送大量消息。
- 适用于批量发送:可以快速发送大量日志或监控数据。
缺点:
- 无法确认消息状态:生产者无法得知消息是否成功到达Broker。
- 可靠性最低:可能会导致消息丢失。
应用场景:
- 监控数据收集:大规模、快速的监控数据收集,允许丢失部分数据。
- 数据流分析:实时数据流处理中,部分数据丢失可以接受。
5.4 批量通信
批量发送
批量发送是指生产者将多条消息打包成一个批次,然后一次性发送给Broker。这种方式可以提高发送效率,但会增加单次发送的复杂度。
优点:
- 提高吞吐量:一次发送多条消息,减少网络IO次数,提升整体效率。
- 降低网络开销:批量发送减少了每条消息的网络开销。
缺点:
- 复杂性增加:需要处理批次内的消息顺序和失败情况。
- 可靠性受影响:如果整个批次发送失败,所有消息都需要重新发送。
应用场景:
- 大数据处理:需要高效发送大量数据的场景,如数据同步、日志传输。
- 批量任务处理:多个任务可以打包一起发送,提高传输效率。
5.5 消息的消费模式
推(Push)模式
在推模式下,Broker主动将消息推送给消费者。消费者只需接收并处理消息。这种模式适合实时性要求高的场景。
优点:
- 实时性强:消息到达Broker后会立即推送给消费者。
- 简单易用:消费者不需要主动拉取消息,减少了处理复杂度。
缺点:
- 容易过载:在高负载情况下,消费者可能处理不过来所有推送的消息,导致过载。
应用场景:
- 实时通知:如交易处理、订单生成的实时推送。
- 实时报警:如监控系统的报警消息推送。
拉(Pull)模式
在拉模式下,消费者主动从Broker中拉取消息。消费者可以控制消息的拉取频率,适用于对消息处理速度有控制要求的场景。
优点:
- 可控性强:消费者可以根据自身的处理能力主动拉取消息,避免过载。
- 适合批量处理:消费者可以一次性拉取多条消息进行批量处理。
缺点:
- 实时性稍差:消息在Broker中等待被拉取,可能会有一定的延迟。
- 实现复杂度高:消费者需要主动管理消息的拉取和处理。
应用场景:
- 定时任务:如批量数据处理、定时同步等。
- 消息积压场景:如消息消费速度慢于生产速度时,拉模式可以避免系统崩溃。
RocketMQ的基本架构
Name Server(命名服务器)
-
作用:
- 服务发现:Name Server 是一个几乎无状态的节点,主要用于服务发现。它存储了所有 Broker 的注册信息,并为 Producer 和 Consumer 提供路由信息。
- 路由管理:Name Server 维护着 Broker 的路由表信息,Producer 和 Consumer 在启动时通过 Name Server 获取 Broker 的地址,从而能够发送或接收消息。
-
工作机制:
- Broker 注册:Broker 在启动时会将自身信息(包括 IP、端口、服务状态等)注册到 Name Server 中。
- 定期心跳:Broker 会定期向 Name Server 发送心跳包,保持自身在 Name Server 上的路由信息更新。
- 路由查找:Producer 或 Consumer 在需要发送或接收消息时,会从 Name Server 获取最新的 Broker 信息。
Broker(消息中间件服务)
-
作用:
- 消息存储:Broker 是实际存储消息的节点,它负责接收 Producer 发送的消息并持久化,同时也为 Consumer 提供消息消费的服务。
- 消息转发:在集群模式下,Broker 可以相互复制消息,提供高可用性和数据冗余。
-
架构层次:
- Master 和 Slave:Broker 节点分为 Master 和 Slave。Master 处理所有的读写请求,而 Slave 作为备份节点提供读请求,或者在 Master 故障时进行切换。
- 消息存储结构:Broker 内部通过 CommitLog 和 ConsumeQueue 两种数据结构来存储消息。CommitLog 负责存储消息的物理数据,ConsumeQueue 则为消息的索引,方便 Consumer 快速消费消息。
-
重要功能:
- 消息刷盘:Broker 支持同步刷盘和异步刷盘,以平衡性能和数据安全性。
- 消息过滤:Broker 提供基于 Tag 的消息过滤功能,减少无关消息的传输和处理。
Producer(消息生产者)
-
作用:
- 发送消息:Producer 是消息的发送者,它将消息发送到 Broker。Producer 可以选择同步发送、异步发送或单向发送。
-
消息发送模式:
- 同步发送:Producer 发送消息后等待 Broker 的确认,适合对可靠性要求高的场景。
- 异步发送:Producer 发送消息后不等待 Broker 的确认,可以更快地返回,适合对实时性要求高的场景。
- 单向发送:Producer 仅发送消息,不关注发送结果,适用于不需要消息确认的场景。
-
负载均衡:
- Producer 会从 Name Server 获取路由信息,根据负载均衡策略将消息发送到适当的 Broker。
Consumer(消息消费者)
-
作用:
- 消费消息:Consumer 从 Broker 中拉取或接收消息,并进行处理。
-
消费模式:
- 推模式:Broker 主动将消息推送给 Consumer,适合实时性要求高的场景。
- 拉模式:Consumer 主动从 Broker 拉取消息,适合批处理和控制消费节奏的场景。
-
消息处理:
- 顺序消费:在需要保持消息顺序的场景中,Consumer 可以保证消息的顺序消费。
- 并发消费:Consumer 可以同时处理多个消息,提高处理能力。
消息存储机制
-
CommitLog:
- CommitLog 是 Broker 用来存储消息的物理文件。消息到达 Broker 后,首先被写入 CommitLog。CommitLog 是一个追加写的文件,具有高效的写入性能。
-
ConsumeQueue:
- ConsumeQueue 是消息的逻辑队列,是 CommitLog 的索引文件。每一个 Topic 对应一个 ConsumeQueue。Consumer 通过 ConsumeQueue 查找到对应的消息物理地址,然后从 CommitLog 中读取消息。
-
Index File(索引文件):
- RocketMQ 提供基于消息键的索引功能,允许 Consumer 按照消息键快速查找消息。这一索引机制基于 HashMap 构建,能快速定位到对应的消息地址。
Name Server、Topic 和 Broker 之间的关系
-
Topic 注册和路由信息:
- 当一个 Broker 启动时,它会将自己上注册的所有 Topic 信息(包括 Topic 所在的队列等)发送到 Name Server。Name Server 记录下这些信息,形成一张路由表。
-
消息发送流程:
- 当 Producer 要发送消息时,它首先会向 Name Server 请求某个 Topic 的路由信息。Name Server 返回该 Topic 对应的所有 Broker 地址及队列信息。
- Producer 根据这些路由信息,将消息发送到适当的 Broker 的队列中。
-
消息消费流程:
- Consumer 在启动时,同样会向 Name Server 请求它感兴趣的 Topic 的路由信息。Name Server 返回该 Topic 所在的 Broker 地址及队列信息。
- Consumer 然后根据这些路由信息,从对应的 Broker 拉取消息。