Files
cs-note/hhs/MQ/12-架构与实战/45-MQ-跨集群复制与容灾.md
T
2026-05-24 20:51:06 +08:00

129 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags:
- MQ
create time: 2026-05-24 19:52
---
# MQ 跨集群复制与容灾
## 概述
当单一 MQ 集群无法满足灾备、合规或多地域低延迟访问的需求时,跨集群复制成为必选项。本文深入分析 Kafka 和 RocketMQ 的跨集群复制方案,探讨 MirrorMaker 2.0 的工作原理,以及异地多活架构的实现思路。
## 正文
### 跨集群复制的需求
为什么不能只靠一个集群?四类典型需求驱动了跨集群复制:
1. **灾备**:主机房不可用时,备集群接管流量,RTO/RPO 需要可控。
2. **数据迁移**:从一个集群迁移到另一个(比如跨云迁移),要求业务无感知。
3. **就近访问**:全球业务需要各区域就近接入,降低网络延迟。
4. **合规要求**:某些数据法规(如 GDPR)要求数据不得离开特定区域,但仍需全局分析。
> [!question]
> 如果你的 MQ 集群需要同时服务中国和欧洲用户,你会选择一个全球集群还是两个区域集群?各自的 Trade-off 是什么?
### Kafka 跨集群方案
**MirrorMaker 2.0**
MirrorMaker 2.0(简称 MM2)是 Kafka 官方的跨集群复制工具,基于 Kafka Connect 构建。它的核心流程很直观:
1. 从远端集群消费消息
2. 写入本地集群的对应 Topic
3. 维护 Offset 映射关系
```mermaid
graph LR
subgraph "源集群 DC-A"
TA["Topic-A"]
TB["Topic-B"]
end
subgraph "MirrorMaker 2.0"
C1["Source Connector"]
T["转换层 - Topic重命名, Offset映射"]
C2["Sink Connector"]
end
subgraph "目标集群 DC-B"
TA2["dc-A.Topic-A"]
TB2["dc-A.Topic-B"]
end
TA --> C1
TB --> C1
C1 --> T
T --> C2
C2 --> TA2
C2 --> TB2
```
MM2 的几个关键设计点:
- **Topic 名称转换**:默认在目标集群加前缀(如 `dc-A.topic-A`),避免命名冲突。
- **Offset 映射**:MM2 会创建一个 `__consumer_offsets` 的映射 Topic,记录源集群和目标集群的 Offset 对应关系。这样消费者在故障切换后能从正确的位置继续消费。
- **自动同步配置**:Topic 分区数、副本因子等配置变更也会自动同步。
```go
// MM2 Offset 映射的核心概念(简化示意)
type OffsetSync struct {
UpstreamOffset int64 // 源集群的 Offset
DownstreamOffset int64 // 目标集群的 Offset
Timestamp int64
}
// 故障切换时,根据映射找到目标集群的对应 Offset
func TranslateOffset(syncs []OffsetSync, upstreamOffset int64) int64 {
// 二分查找最近的映射点
for i := len(syncs) - 1; i >= 0; i-- {
if syncs[i].UpstreamOffset <= upstreamOffset {
return syncs[i].DownstreamOffset
}
}
return 0
}
```
**Confluent Replicator**
Confluent 的商业方案,相比 MM2 更成熟,支持自动 Topic 创建、配置同步、Offset 翻译,但需要 Confluent Platform 授权。
**Cluster Linking(Confluent 7.0+)**
这是 Confluent 最新的方案,直接在 Broker 层面建立集群间的链接,不需要额外的 Connect 集群。性能更好,延迟更低,但仅限 Confluent 平台。
### RocketMQ 跨集群方案
RocketMQ 的跨集群方案相对简单:
- **DLedger 多副本**:基于 Raft 协议的副本同步,适合同城双活场景,RPO = 0。
- **RocketMQ Bridge**:类似 Kafka MM2 的桥接组件,支持跨集群消息转发。
### 跨地域同步的挑战
跨集群复制不是简单的消息转发,面临几个硬核挑战:
**网络延迟**:跨地域网络延迟通常 50-200ms,同步复制会严重影响吞吐。大多数场景只能用异步复制,这意味着 RPO > 0。
**消息顺序**:源集群保证了分区内的顺序,但复制到目标集群后,由于网络抖动和并行复制,可能出现乱序。解决方案是按 Key 哈希到同一分区,牺牲并行度换取顺序。
**冲突解决**:双向复制(Active-Active)场景下,两端可能同时修改同一份数据。常见策略有 Last-Write-Wins(LWW)和基于版本号的冲突检测。
**带宽成本**:跨地域带宽昂贵。可以通过压缩、批量发送、限速等手段控制成本。
### 异地多活架构
异地多活是最复杂的跨地域方案,核心思想是每个区域都能独立提供完整服务:
- **写本地读本地**:每个区域的 Producer 和 Consumer 都连接本地集群,避免跨地域调用。
- **全局 Topic 路由**:通过全局路由层,将请求导向用户所在的区域集群。
- **冲突检测与合并**:对于需要全局一致的数据,采用 CDC(Change Data Capture)+ 冲突解决机制。
> [!question]
> 异地多活下,如果用户 A 在中国下单,同时用户 B 在美国查看库存,如何保证库存数据的一致性?
## 关联笔记
- [[44-MQ-高可用架构]]
- [[46-MQ-分布式事务实践]]
- [[51-云消息服务]]