基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

RocketMQ Broker 的主从架构(Master/Slave)是如何同步数据的?

知识点图片

RocketMQ主从同步采用拉模式,Slave通过专用通道从Master拉取核心数据CommitLog,并在本地重建索引。提供同步和异步复制模式,以实现Broker高可用。

我们来详细解析一下 RocketMQ Broker 主从架构(Master/Slave)的数据同步机制。

核心思想:基于 CommitLog 的主从复制

RocketMQ 的主从同步核心思想非常清晰:Slave Broker 伪装成一个特殊的客户端,主动从 Master Broker 拉取(Pull)数据

这个过程同步的主要数据是 CommitLog 文件,它是 RocketMQ 中存储所有消息的物理文件。只要 Master 和 Slave 的 CommitLog 文件保持一致,那么 Slave 就可以通过重新解析 CommitLog 来构建出与 Master 完全相同的其他逻辑数据,如 ConsumeQueueIndexFile


数据同步的详细流程

这个过程可以分解为以下几个关键步骤:

1. 建立连接(HA Connection)

  • 启动与注册:当一个 Slave Broker 启动时,它会像 Master 一样向 NameServer 注册。在注册信息中,它会明确自己的角色是 Slave,并带上自己的 BrokerId(非 0,Master 的 BrokerId 为 0)以及所属 Master 的地址。
  • 建立主从连接:Slave 启动后,内部会有一个名为 HAService 的服务。该服务会启动一个客户端(HAClient),主动连接到其配置的 Master Broker 的 HAService 端口(默认为 Master监听端口 + 1,例如 10912)。
  • 长连接通道:一旦连接成功,Master 和 Slave 之间就建立了一个专门用于数据同步的长连接 TCP 通道,我们称之为 HA Channel

2. 发起数据拉取请求

  • 报告自身进度:连接建立后,Slave 会立即向 Master 发送第一个数据拉取请求。这个请求中最重要的信息是 Slave 当前 CommitLog 文件中已同步的最大物理偏移量(maxPhyOffset)
    • 如果 Slave 是第一次启动,这个偏移量就是 0。
    • 如果 Slave 是重启,它会读取本地 CommitLog 的大小,将该值作为起始偏移量。
  • 持续拉取循环:这个请求-响应的过程会形成一个持续不断的循环,确保数据近乎实时地同步。

3. Master 处理请求并返回数据

  • 定位数据:Master 的 HAService 收到 Slave 的请求后,获取到 Slave 请求的 offset
  • 读取数据:Master 会从自己的 CommitLog 文件中,从该 offset 开始向后读取一段数据(例如,默认一次最多读取 32KB)。
  • 数据打包:Master 将读取到的 CommitLog 数据块,连同这段数据的起始偏移量和总长度,打包成一个响应包。
  • 发送数据:通过 HA Channel 将这个响应包发送给 Slave。
  • 等待下一次请求:如果 Master 发现 Slave 请求的 offset 已经追上了自己的最新进度(即没有新消息了),Master 会挂起(hold)这个请求,等待新的消息写入后,再将新消息返回给 Slave,这是一种高效的 长轮询(Long Polling)机制,避免了 Slave 无效的空轮询。

4. Slave 处理数据并更新进度

  • 接收数据:Slave 的 HAClient 接收到 Master 发来的数据包。
  • 解析并写入:Slave 解析数据包,提取出 CommitLog 数据,并将其顺序追加到自己的 CommitLog 文件中。
  • 更新本地偏移量:写入成功后,Slave 更新自己内存中记录的 maxPhyOffset
  • 发起下一次请求:Slave 立即使用这个新的 maxPhyOffset 作为请求参数,向 Master 发起下一次数据拉取请求。

通过这个 “Slave请求 -> Master响应 -> Slave写入 -> Slave再请求” 的闭环,Slave 不断地从 Master 拉取增量数据,从而使自己的 CommitLog 与 Master 保持同步。


同步了哪些数据?

  1. 核心数据:CommitLog

    • 这是主从同步的唯一通道传输的核心业务数据。所有 Topic 的消息都混合存储在 CommitLog 中。
  2. 元数据(Metadata)

    • 除了消息实体,Broker 的正常运行还需要很多元数据,例如 Topic 配置、消费组配置、消费进度(Consumer Offset)等。
    • 这些元数据的同步不通过 HA Channel。而是 Master Broker 在收到配置变更或定时任务触发时,通过一个普通的 RPC 请求,将 topics.json, subscriptionGroup.json, consumerOffset.json 等配置文件的内容同步给所有关联的 Slave。这确保了主从在配置层面也是一致的。
  3. 自构建数据:ConsumeQueue 和 IndexFile

    • 这两个文件是消息的“索引”,用于加速消费和查询。
    • 它们不会通过网络从 Master 同步到 Slave。
    • Slave 上有一个独立的线程(ReputMessageService),它会实时地扫描本地 CommitLog 中新增的数据,然后像 Master 一样,在本地重新构建 ConsumeQueueIndexFile
    • 这种设计的巨大好处是简化了同步逻辑,主从同步只用关心单一的、顺序写的 CommitLog 文件,大大降低了复杂性和出错的概率。

两种同步模式

RocketMQ 提供了两种主从同步模式,以平衡数据可靠性和消息发送性能。这主要影响 Producer 发送消息的流程。

1. 同步复制 (Synchronous Replication - SYNC_MASTER)

这是默认和推荐的模式,提供最高的数据可靠性。

  • 流程
    1. Producer 发送消息到 Master Broker。
    2. Master 将消息写入自己的 CommitLog
    3. Master 等待,直到消息通过 HA Channel 成功同步到至少一个 Slave Broker。
    4. Slave 返回确认信息给 Master。
    5. Master 收到 Slave 的确认后,才向 Producer 返回 "发送成功" 的响应。
  • 优点:数据零丢失。即使 Master 在返回成功后立即宕机,消息也已经在 Slave 上有备份,可以保证不丢失。
  • 缺点:增加了消息发送的延迟(RT),因为需要等待一次主从网络交互。

2. 异步复制 (Asynchronous Replication - ASYNC_MASTER)

这种模式下,性能更高,但存在丢失少量数据的风险。

  • 流程
    1. Producer 发送消息到 Master Broker。
    2. Master 将消息写入自己的 CommitLog 后,立即向 Producer 返回 "发送成功" 的响应。
    3. Master 在后台异步地将消息推送给 Slave。
  • 优点:消息发送延迟低,吞吐量更高。
  • 缺点:如果 Master 在返回成功后、但消息还未同步到 Slave 之前突然宕机(例如磁盘损坏、断电),那么这部分消息就会永久丢失。

总结

特性 描述
同步模型 拉模式(Pull Model):Slave 主动向 Master 拉取数据。
核心通道 HA Channel:一个专用于数据复制的长连接。
同步内容 主要同步 CommitLog 文件。
索引构建 ConsumeQueueIndexFile 在 Slave 端本地重建,不通过网络传输。
元数据同步 Topic、消费组等配置信息通过独立的 RPC 进行同步。
复制模式 提供同步复制异步复制两种模式,用于在可靠性和性能之间做权衡。
设计目标 实现 Broker 的高可用(High Availability),当 Master 宕机时,Slave 可以无缝(或少量数据丢失)接替工作。
00:00
00:00