未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用边界与维护说明

本文适合具备 Kafka、Kafka Connect 和分布式系统基础的读者,用于多集群场景分析、MM2 配置草案、位点迁移练习及带宽估算,不是可直接执行的生产切换手册。启动验证与计划切换中的两条复制监控命令仍含未引用的“>”,会被 shell 解释为输出重定向,且正文未建立示例消费者组的部署依据,不能用其判定复制进度。切换流程仅适用于源集群仍可访问的计划切换;位点迁移代码已修正,但读取位置设置不等于位点提交,也不独立保证业务无重复或无丢失。吞吐与压缩比例已限定为需实测的规划假设,RTO、RPO 和延迟值应作为待验证设计目标;商业产品的规模适用性与排他性选型建议缺少论证,不宜作为采购结论。本次仅作全文结构审阅,未进行外部事实核验、代码运行或部署验证。 已取消无法确定目标的可点击引用「02-Kafka架构原理」,保留原提及;Missing link target: 02-Kafka架构原理 已取消无法确定目标的可点击引用「分布式系统基础」,保留原提及;Missing link target: 分布式系统基础

多集群架构设计 - 企业级 Kafka 部署策略

abstract 本节概览

  • 学习目标:理解多集群使用场景,掌握 MirrorMaker 2 配置、主备切换和双活架构设计
  • 前置知识:KSQL 流式 SQL、Kafka 架构基础
  • 预计用时:45 分钟
  • 后续学习:故障处理与恢复

单集群能处理绝大多数企业场景,但当业务规模增长、合规要求提升、或需要跨区域部署时,多集群架构就成了必选项。本文系统梳理各类多集群场景、核心工具 MirrorMaker 2 的配置细节,以及生产级别的切换策略。

多集群的四类使用场景

不同场景对多集群的需求差异显著,在架构设计之初就要明确目的:

场景 核心需求 数据流向 关键指标
灾备(DR) 主集群故障时快速切换 主 → 备,单向 RTO < 30min,RPO < 5min
地理分布 降低跨地域访问延迟 双向或汇聚 本地延迟 < 5ms
数据汇聚 多个边缘集群数据汇入中心 多 → 一,单向 带宽利用率、数据完整性
业务隔离 不同业务/环境(生产/测试)隔离 无复制或单向 资源隔离、安全边界

note 优先考虑单集群方案

多集群显著增加运维复杂度。在引入多集群前,先评估单集群扩容(增加 Broker、分区)是否可以满足需求。若容量规划以单集群百万级 TPS 为假设,需在目标消息大小、分区布局、硬件和可靠性配置下通过压测验证,不能将其视为通用能力保证。


MirrorMaker 2:跨集群复制的标准方案

MirrorMaker 2(简称 MM2)是 Kafka 2.4 内置的跨集群复制工具,基于 Kafka Connect 框架构建,相比 MirrorMaker 1 有本质性改进:

  • 基于 Connect 框架,支持动态配置和状态追踪
  • 自动同步 Topic 配置、ACL
  • 内置心跳(Heartbeat)和检查点(Checkpoint)机制,支持消费者 Offset 迁移
  • Topic 命名加前缀(source-cluster.topic-name),避免循环复制

mm2.properties 配置详解

# ===================================================
# MirrorMaker 2 配置文件:mm2.properties
# 场景:source 集群 → target 集群,单向灾备复制
# ===================================================

# 1. 集群别名定义(用英文简称,后续引用)
clusters = source, target

# 2. 各集群的连接地址
source.bootstrap.servers = source-kafka-01:9092,source-kafka-02:9092,source-kafka-03:9092
target.bootstrap.servers = target-kafka-01:9092,target-kafka-02:9092,target-kafka-03:9092

# 3. 开启 source → target 的复制链路
source->target.enabled = true

# 4. 需要复制的 Topic(支持正则,.* 表示全部)
source->target.topics = order-events, user-events, payment-events

# 如需排除某些 Topic:
# source->target.topics.blacklist = __consumer_offsets, _schemas

# 5. 心跳 Topic:消费者用于检测 source 集群是否可达
emit.heartbeats.enabled = true
heartbeats.topic.replication.factor = 3

# 6. 检查点:将 source 集群的 Consumer Offset 映射到 target 集群
emit.checkpoints.enabled = true
emit.checkpoints.interval.seconds = 60
checkpoints.topic.replication.factor = 3

# 7. 同步 Topic 配置(分区数、保留时间等)和 ACL
sync.topic.configs.enabled = true
sync.topic.acls.enabled = false    # 生产环境按需开启

# 8. Topic 命名策略,默认在前面加集群别名前缀
# target 集群上的 Topic 名称变为:source.order-events
replication.policy.class = org.apache.kafka.connect.mirror.DefaultReplicationPolicy
replication.policy.separator = .

# 9. 性能配置
tasks.max = 8                            # 复制任务并发上限;结合可分配分区数、吞吐需求和资源约束评估
offset.lag.max = 5000                    # 控制位点同步记录生成频率的滞后阈值,不保证复制滞后不超过此值

# 10. Kafka Connect 配置(MM2 以 Connect 模式运行)
source.config.storage.replication.factor = 3
source.offset.storage.replication.factor = 3
source.status.storage.replication.factor = 3

启动 MirrorMaker 2

# 专用模式(推荐生产使用,单独进程)
connect-mirror-maker.sh mm2.properties

# 分布式模式(利用现有 Connect 集群)
# 通过 REST API 提交 MirrorSourceConnector、MirrorCheckpointConnector、MirrorHeartbeatConnector

# 验证 target 集群上的镜像 Topic 是否创建成功
kafka-topics.sh --bootstrap-server target-kafka-01:9092 --list | grep "^source\."
# 期望输出:source.order-events  source.user-events  ...

# 查看复制延迟(Consumer Lag)
kafka-consumer-groups.sh --bootstrap-server source-kafka-01:9092 \
  --describe --group mm2-source->target-replication-group

MirrorMaker 2 内部三个连接器的职责

连接器 功能 创建的 Topic
MirrorSourceConnector 复制消息数据,同步 Topic 配置 source.<topic-name>
MirrorCheckpointConnector 翻译并存储 Consumer Offset 映射关系 source.checkpoints.internal
MirrorHeartbeatConnector 发送心跳,监测链路存活 heartbeats

主备切换:Consumer Offset 迁移

灾备场景的重要挑战是控制切换时的重复消费和数据丢失风险。MM2 的 Checkpoint 机制提供消费者位点翻译,但不能单独保证不重复、不丢失;还需结合复制进度、检查点更新、业务幂等与切换流程评估。

Offset 迁移原理

MM2 定期将 source 集群的 Consumer Offset 翻译成 target 集群等价 Offset,写入 source.checkpoints.internal Topic。切换时,消费者可以查询这个映射关系,直接从正确位置继续消费。

// 主备切换时,使用 RemoteClusterUtils 获取翻译后的 Offset
Map<TopicPartition, OffsetAndMetadata> translatedOffsets =
    RemoteClusterUtils.translateOffsets(
        targetConsumerConfig,         // target 集群的 Consumer 配置
        "source",                     // source 集群别名
        "my-consumer-group",          // 要迁移的 Consumer Group
        Duration.ofSeconds(30)        // 等待超时
    );

// 使用翻译后的 Offset 设置 target 消费者的读取位置;这里不执行位点提交
KafkaConsumer<String, String> targetConsumer = new KafkaConsumer<>(targetConsumerConfig);
targetConsumer.assign(translatedOffsets.keySet());
translatedOffsets.forEach((partition, offsetAndMetadata) ->
    targetConsumer.seek(partition, offsetAndMetadata.offset()));
// 此后从翻译后的位点消费;仍需处理检查点滞后、重复消费和未复制数据的风险

源集群仍可访问时的计划切换流程草案

# Step 1:确认复制延迟已降至可接受范围(建议 < 1 分钟)
kafka-consumer-groups.sh --bootstrap-server target-kafka-01:9092 \
  --describe --group mm2-source->target-replication-group

# Step 2:停止向 source 集群的写入(或触发业务层面的流量切换)

# Step 3:等待 target 集群追上 source(Lag 降至 0)
# 结合 MM2 复制指标和业务数据校验确认复制进度,不直接比较源与目标的 Offset 数值

# Step 4:通过 RemoteClusterUtils 迁移 Consumer Offset(见上方代码)

# Step 5:将消费者 bootstrap.servers 切换到 target 集群,启动消费

# Step 6:验证业务数据正确性,观察 5 分钟

# Step 7(可选):开启反向复制 target→source,为回切做准备

主主双活架构

双活比灾备复杂得多,核心挑战是写冲突和循环复制。

设计原则

写本地、读本地: 每个区域的应用只写本地集群,通过 MM2 双向复制将数据同步到对方。业务层面通过路由策略保证同一用户的数据始终写入同一集群。

防止循环复制: MM2 在复制消息时会打上来源标记(通过 Topic 前缀区分)。DefaultReplicationPolicy 会忽略已带有远端前缀的 Topic,避免 A→B 的消息再被 B→A 复制回去。

Topic 命名约定

# 集群 A 本地 Topic(应用直接写)
topic-name

# 集群 A 在集群 B 上的镜像(MM2 自动创建,应用只读不写)
cluster-a.topic-name

# 双活配置示例
clusters = cluster-a, cluster-b

cluster-a.bootstrap.servers = kafka-a-01:9092,kafka-a-02:9092
cluster-b.bootstrap.servers = kafka-b-01:9092,kafka-b-02:9092

# 双向复制
cluster-a->cluster-b.enabled = true
cluster-b->cluster-a.enabled = true

cluster-a->cluster-b.topics = .*
cluster-b->cluster-a.topics = .*

warning 双活的业务层约束

双活不是"随便往任何集群写"。必须在业务层实现分片写入(例如按用户 ID 的哈希值决定写哪个集群),确保同一实体的数据不会出现写冲突。如果做不到,请退回到主备模式。


Confluent Replicator vs MirrorMaker 2

对比维度 MirrorMaker 2(开源) Confluent Replicator(商业)
授权 Apache 2.0,完全免费 需要 Confluent Platform 许可证
Offset 迁移 可通过 RemoteClusterUtils 编写位点迁移代码 自动迁移能力及额外代码需求取决于版本、配置和使用场景
监控可观测性 JMX 指标,需自建监控 Confluent Control Center 集成
配置复杂度 中等(properties 文件) 较低(GUI 可操作)
压缩格式兼容 需结合部署版本和消息压缩配置评估 需结合部署版本及其支持的压缩格式评估,不能假定支持所有格式
适用规模 中小型到大型 超大型企业、严格 SLA 要求

对大多数企业,MirrorMaker 2 已完全够用。仅在有 Confluent Platform 合约且需要图形化运维的场景才值得评估 Replicator。


集群联邦:多业务域汇聚架构

适用于大型企业有多条业务线,各自独立运营集群,但需要统一接入数据湖的场景:

业务集群 A(订单)───┐
业务集群 B(用户)───┼──► 汇聚集群(中央)──► 数据湖(HDFS / S3)
业务集群 C(支付)───┘

汇聚集群的职责:

  • 接收各业务集群的镜像数据(通过 MM2)
  • 统一做格式转换和脱敏处理
  • 输出到数据湖或下游分析系统

配置示例(汇聚集群接收多个 Source):

clusters = orders, users, payments, central

orders.bootstrap.servers  = orders-kafka:9092
users.bootstrap.servers   = users-kafka:9092
payments.bootstrap.servers = payments-kafka:9092
central.bootstrap.servers = central-kafka:9092

orders->central.enabled   = true
users->central.enabled    = true
payments->central.enabled = true

# 各业务集群只复制各自的核心 Topic
orders->central.topics   = order-events, order-status
users->central.topics    = user-registration, user-profile
payments->central.topics = payment-events, refund-events

跨机房带宽规划

跨机房复制的带宽需求估算公式:

带宽需求(Mbps)= 峰值 TPS × 平均消息大小(字节)× 8 × 跨集群复制份数 × 安全系数 ÷ 1,000,000

示例:
  峰值 TPS         = 50,000 条/秒
  平均消息大小      = 2,000 字节
  MM2 复制因子      = 1(只复制一份)
  安全系数          = 1.3(留 30% 余量)

带宽需求 = 50,000 × 2,000 × 8 × 1 × 1.3 ÷ 1,000,000 ≈ 1,040 Mbps ≈ 1 Gbps

tip 带宽优化手段

  • 评估在 MM2 生产者配置中开启压缩(compression.type=lz4);若以体积减少 50-70% 为规划假设,应通过实际消息样本测试验证
  • 跨机房专线优先于公网,延迟稳定性更好
  • 考虑在 source 侧部署边缘 Agent 做预聚合,减少实际传输量

掌握检查

  • [ ] 能说出灾备、地理分布、数据汇聚、业务隔离四种多集群场景的核心差异
  • [ ] 理解 MM2 的三个内置 Connector(Source/Checkpoint/Heartbeat)各自的职责
  • [ ] 能写出 mm2.properties 的核心配置段,并解释每个参数的作用
  • [ ] 理解 Consumer Offset 迁移的原理,能说出 RemoteClusterUtils.translateOffsets() 的使用时机
  • [ ] 能说出主主双活防止循环复制的机制(Topic 前缀 + DefaultReplicationPolicy)
  • [ ] 能用公式估算跨机房复制的带宽需求

练习题

  1. 公司在上海和北京各有一个 Kafka 集群,需要实现灾备(上海为主,北京为备)。请画出架构图,并列出 mm2.properties 的关键配置。
  2. 灾备切换后,原来消费 order-events Topic 的消费者组 order-processor 如何利用检查点迁移到北京集群,并控制重复消费风险?请写出关键代码片段,说明复制滞后、检查点更新及业务幂等对迁移的影响。
  3. 如果同时有 5 个业务集群需要向中央汇聚集群复制数据,tasks.max 参数应该怎么设置?有什么注意事项?

学习连接

前置知识: KSQL 流式 SQL - 流式数据查询 下一步: 故障处理与恢复 - 灾难恢复策略 相关概念: 分布式系统、数据湖接入


tip 多集群架构的核心原则

  • 从单集群开始:不要过度设计,先验证业务规模再引入多集群
  • 明确数据所有权:每个 Topic 只有一个主集群负责写入
  • 测试切换流程:灾备的价值在于真的能切,定期演练是必须的
  • 监控复制延迟:结合 MM2 连接器指标、检查点新鲜度与业务数据校验评估健康状况,不能假定示例消费者组能够代表复制进度
  • 带宽预算先行:跨机房专线需要提前申请,别等到需要时再规划