RocketMQ 4.x 入门教程之二

大纲

前言

学习资源

版本说明

本文所使用的各软件版本如下表所示:

组件版本说明
JDK11Java、SpringBoot、SpringCloud 项目案例使用的 JDK 版本
RocketMQ Server4.9.0RocketMQ 服务端(包括 NameServer 和 Broker),运行时依赖 JDK 1.8+

RocketMQ 单机部署实战

Linux 安装 RocketMQ 单机

Docker 安装 RocketMQ 单机

RocketMQ 集群部署理论

集群部署的整体架构

NameServer 集群说明

NameServer 集群是无状态的,去中心化的,即 NameServer 集群中的各个节点间是没有地位差异,各节点之间相互不进行信息通讯。那各节点中的数据是如何进行数据同步的呢?在 Broker 节点启动时,会轮询 NameServer 列表,与 NameServer 集群中的所有节点建立长连接,并定时向所有 NameServer 节点注册 Topic 路由信息,以保证路由信息的一致性与可用性。在每个 NameServer 的内部维护着⼀个完整的 Broker 列表,用来动态存储 Broker 的信息。

Broker 集群说明

Broker 集群本质上是一个主从集群,集群节点分为 Master 节点 与 Slave 节点两种角色,其中 Master 节点负责处理读写操作请求,Slave 节点负责对 Master 节点中的数据进行同步备份。当 Master 节点宕机后,在具备自动切换能力(例如 DLedger 模式或者 Controller 模式)的情况下,Slave 节点可以被提升为 Master 节点继续对外提供服务,因此整体上可以看作主备架构。特别注意,在 RocketMQ 4.5 版本之前,传统的主从架构并不支持自动主从切换;RocketMQ 从 4.5 版本开始引入 DLedger 模式后,才开始支持自动主从切换;5.x 版本又引入了 Controller 模式,但只有手动开启 Controller 才支持自动切换,否则仍然不具备自动主从切换能力。

数据复制与刷盘策略

复制策略

在 RocketMQ 中,复制策略是指 Broker 的 Master 节点与 Slave 节点之间的数据同步方式。RocketMQ 主要提供两种复制策略:

  • 同步复制:消息写入 Master 节点后,Master 节点会等待 Slave 节点同步数据成功后才向 Producer 返回成功(ACK)。
  • 异步复制:消息写入 Master 节点后,Master 节点立即向 Producer 返回成功(ACK),无需等待 Slave 节点同步数据成功。

异步复制策略可以降低系统的写入延迟,RT(响应时间)更小,提高系统的吞吐量。

刷盘策略

在 RocketMQ 中,刷盘策略是指 Broker 中消息从内存(PageCache)持久化到磁盘的方式。当消息写入 Broker 后,需要通过刷盘机制将数据从内存(PageCache)落到磁盘,以保证数据的可靠性。RocketMQ 主要提供两种刷盘策略:

  • 同步刷盘(SYNC_FLUSH)

    • 当消息真正持久化到磁盘后,才返回写入成功(ACK)
    • 数据可靠性高,即使 Broker 宕机也不易丢失数据
    • 但由于需要等待磁盘 I/O 完成,写入延迟较高,吞吐量相对较低
  • 异步刷盘(ASYNC_FLUSH)

    • 当消息写入到 Broker 的内存(PageCache)后,即可返回写入成功(ACK)
    • 不需要等待 Broker 将消息持久化到磁盘

异步刷盘补充说明(重点):

  • (1) 异步刷盘可以显著降低写入延迟(RT 更小),从而提升系统吞吐量
  • (2) 将消息写入 “内存”,通常是指写入 PageCache(操作系统页缓存),而不是直接写入物理磁盘
  • (3) 在异步刷盘模式下:
    • 消息写入 PageCache 后,就可以立即返回写入成功(ACK)
    • 并不会立刻执行磁盘落盘操作
    • 由操作系统在合适的时机(如 PageCache 大小达到一定阈值或触发刷盘机制)异步刷新到物理磁盘

总结

同步刷盘可以保证数据安全但性能较低,异步刷盘可以提升性能但存在极端情况下的数据丢失风险,两者的本质区别在于是否等待磁盘落盘完成后再返回写入成功(ACK)。

Broker 的集群模式

在 RocketMQ 中,根据 Broker 集群中各个节点间关系的不同,Broker 的集群模式可以分为以下几类。

单 Master 集群模式

在 RocketMQ 中,单 Master 集群模式是指只有一个 Broker(其本质上就不能称为集群)。这种方式也只能是在测试时使用,生产环境下不能使用,因为存在单点故障问题。

多 Master 集群模式

在 RocketMQ 中,多 Master 集群模式是指 Broker 集群仅由多个 Master 节点组成,不包含 Slave 节点。同一 Topic 的多个 Queue(分区)会分散在不同的 Master 节点上。

  • 优点:

    • 架构简单,部署和维护成本低;
    • 单个 Master 节点宕机或重启时,仅影响该节点上的消息,不影响整体服务的可用性;
    • 在所有 Master 节点都配置了 RAID(如 RAID10)磁盘阵列且使用同步刷盘时,数据可靠性很高(同步刷盘不会丢失任何一条消息,异步刷盘可能会丢少量消息),整体性能最高
  • 缺点:

    • 某个 Master 节点宕机期间,该节点上未消费的消息无法被消费,消息实时性会受到影响;
    • 无 Slave 节点进行数据备份和主从切换,一旦 Master 节点宕机,该节点上的消息将不可被消费,存在节点级的单点故障问题。
  • 注意:

    • 上述 “数据可靠性很高” 的优点,其前提是所有 Master 节点都配置了 RAID(如 RAID10)磁盘阵列,并使用同步刷盘策略。
    • 若未配置物理磁盘冗余,一旦 Master 节点宕机(比如单个磁盘损坏),可能会导致大量数据丢失。

RAID 磁盘阵列说明

  • RAID10(也称 RAID 1 + 0)是将数据先做镜像(RAID1),再进行数据条带化(RAID0)的磁盘阵列;即先保证数据冗余,再提升读写性能。
  • 数据条带化(RAID0)就是将数据拆分成多个块并行写入多个物理磁盘,以提升读写性能。RAID10 则是在此基础上叠加镜像(RAID1),实现高性能与高可靠性的平衡,允许部分物理磁盘出现故障而不丢失数据。
  • RAID(如 RAID10)只能提升单机物理磁盘层面的可靠性,不能消除 Broker 级别(应用服务级别)的单点故障;多 Master 节点集群架构在没有 Slave 节点的情况下,仍然存在节点级的单点故障问题

多 Master 多 Slave 集群模式 - 异步复制

Broker 集群由多个 Master 节点组成,每个 Master 节点可配置一个或多个 Slave 节点(在配置 RAID10 磁盘阵列的情况下,通常一个 Master 节点对应一个 Slave 节点即可)。Master 节点与 Slave 节点为主备关系:Master 节点负责消息的读写,Slave 节点负责数据备份及在 Master 节点宕机后的角色切换。

  • 异步复制是指消息写入 Master 节点后,立即向 Producer 返回成功(ACK),而无需等待 Slave 节点完成数据同步。
  • 由于异步复制存在短暂的延迟(毫秒级),所以当 Master 节点宕机后,这种异步复制方式可能会存在丢失少量消息的问题。
  • 在 Master 节点没有配置 RAID10 磁盘阵列的情况下,即使单个磁盘损坏,丢失的消息也非常少,且消息实时性不会受影响(自动主从切换生效的情况下)。
  • 在 RocketMQ 4.5 版本之前的传统多 Master 多 Slave 架构(无论同步复制,还是异步复制)中,一旦 Master 节点宕机,Slave 节点不会自动切换为 Master 节点,需要人工干预。RocketMQ 从 4.5 版本开始引入 DLedger 模式后,才开始支持自动主从切换。

特别注意

Slave 节点从 Master 节点同步数据的延迟越短,可能丢失的消息就越少。对于多 Master 集群模式 + RAID10 磁盘阵列,如果 Master 节点采用异步刷盘策略,由于数据先写入 PageCache 后再异步刷入磁盘,在刷盘完成前若 Master 节点发生宕机,同样会存在延迟刷盘导致的数据丢失问题;但由于 RAID10 磁盘阵列的数据同步通常为微秒级(由硬件实现支持),因此丢失的数据量会更少。

多 Master 多 Slave 集群模式 - 同步复制

该 Broker 集群模式是多 Master 多 Slave 架构的同步复制实现。同步复制是指消息写入 Master 节点后,Master 节点会等待 Slave 节点完成数据同步,然后才向 Producer 返回成功(ACK),即 Master 节点与 Slave 节点都写入成功后才返回确认(也就是所谓的同步双写)。

  • 同步复制模式与异步复制模式相比,该模式的优点是消息安全性更高,基本不会发生消息丢失。但由于需要等待 Slave 节点数据同步完成,单条消息的 RT(响应时间)会略有增加,整体性能约下降 10% 左右。
  • 在 RocketMQ 4.5 版本之前的传统多 Master 多 Slave 架构(无论同步复制,还是异步复制)中,一旦 Master 节点宕机,Slave 节点不会自动切换为 Master 节点,需要人工干预。RocketMQ 从 4.5 版本开始引入 DLedger 模式后,才开始支持自动主从切换。

RocketMQ 不同版本对自动主从切换的支持

  • RocketMQ 4.5 版本之前:采用传统 Master-Slave 架构,不支持自动主从切换,一旦 Master 节点宕机,Slave 节点不会自动升级为 Master 节点,需要人工干预恢复服务。
  • RocketMQ 4.5 版本及之后:引入基于 Raft 协议的 DLedger 模式,支持自动 Leader 选举(相当于自动 Master)、节点故障自动切换以及强一致性复制,可以实现高可用。
  • RocketMQ 5.x 版本:引入 Controller 模式(官方推荐),支持主从自动切换,可独立部署 Controller 组件,具备更高灵活性,逐步替代 DLedger 模式。手动开启 Controller 才支持自动切换,否则仍不具备自动主从切换能力。

Broker 集群模式选择的最佳实践

  • 在生产环境中,推荐搭建双主双从(2M-2S)的 Broker 集群,主从节点之间采用异步复制策略,并采用异步刷盘策略,同时为每个 Master 节点配置 RAID10 磁盘阵列。这样既利用了 RAID10 的高性能和高可靠性,又可以通过 Slave 节点分摊读取(如消息订阅 / 消费)压力,避免 Master 节点负载过高而影响订阅性能与系统稳定性。RAID10 磁盘阵列的效率要高于 Master-Slave 集群架构,因为 RAID10 是硬件支持的;也正因为如此,所以 RAID10 磁盘阵列的搭建成本较高。
  • 特别注意,为了避免单个磁盘损坏造成数据丢失,并提升磁盘读写性能,所有 Master 节点都必须配置 RAID10 磁盘阵列作为基础保障。异步刷盘解决的是写入性能问题,RAID10 磁盘阵列解决的是磁盘可靠性问题,两者都无法避免 “刷盘前” 这段时间窗口的数据丢失,除非是使用同步刷盘。
  • RocketMQ 的 Slave 节点是可以读的(不可以写),但默认情况下 Consumer 只会从 Master 节点拉取消息;通过配置可以让 Consumer 从 Slave 节点消费,从而实现读写分离,不过由于 Slave 节点的数据可能存在同步延迟(采用异步复制策略时),所以读写分离一般只适用于对实时性要求不高的场景。

多 Master 集群 + RAID10 磁盘阵列与多 Master 多 Slave 集群的区别是什么?

  • 多 Master 集群 + RAID10 磁盘阵列只能保证数据不丢失、不影响消息写入,但在高负载下可能影响消息订阅;同时单个 Broker 仍存在单点故障问题(RAID10 磁盘阵列只保证磁盘可靠性,不保证进程可用性),Master 节点宕机后无法自动恢复,对 Broker 可用性保障较弱,不过其整体执行效率要远高于多 Master 多 Slave 集群。
  • 多 Master 多 Slave 集群不仅可以保证数据不丢失、且不影响消息写入,还可以通过 Slave 节点分担读取压力避免影响订阅;同时具备更高的 Broker 可用性(具备容灾能力),但在传统的主从模式下不支持自动主从切换(需人工介入,或依赖 DLedger / Controller 模式实现自动主从切换);由于有数据同步的开销,其整体运行效率低于多 Master 集群 + RAID10 磁盘阵列。

RocketMQ 集群部署实战

Linux 搭建 RocketMQ 集群