系统学习 学习路径总入口:先选领域,再建立模型,最后用故障演练验证

版本信息最后核对:2026-10-25

在 Kafka 集群中安全替换或退役 broker,迁移分区副本,并验证 controller 选举、ISR、生产与消费链路

适用场景

先区分“替换 broker”和“重建副本”。替换只是把进程或主机换掉,分区数据仍由其他副本提供;如果某个分区只剩一份副本,替换前必须先确认这份数据可用并完成备份,否则重启或迁移都可能造成不可恢复的丢失。还要确认集群的元数据模式:KRaft 使用 controller quorum,ZooKeeper 使用独立或合并的 controller 选举,两者的替换步骤和风险边界不同。

前置检查

  1. 确认集群身份、元数据模式和节点清单。记录 cluster ID、每个 broker 的 node ID、角色、机架和日志目录,避免把新节点误加入另一个集群:
kafka-cluster.sh cluster-id --bootstrap-server "$BS"
kafka-metadata-quorum.sh --bootstrap-server "$BS" describe --status
kafka-broker-api-versions.sh --bootstrap-server "$BS"
kafka-topics.sh --bootstrap-server "$BS" --describe --under-replicated-partitions

KRaft 集群重点看 controller quorum 是否健康、active controller 是谁、voter 数量是否完整;ZooKeeper 集群检查 controller 是否稳定、ZooKeeper ensemble 是否健康。替换 controller 前,必须保证剩余节点仍能形成多数派。

  1. 评估容量和副本分布。按 broker 汇总日志目录大小、分区数量、leader 数量和磁盘余量,确认新节点容量不低于旧节点,且迁移后不会让其他 broker 超出水位:
kafka-log-dirs.sh --bootstrap-server "$BS" --describe
kafka-topics.sh --bootstrap-server "$BS" --describe
kafka-consumer-groups.sh --bootstrap-server "$BS" --list

同时检查机架感知配置。如果副本都集中在同一机架,单机架故障仍可能丢数据;迁移计划应让每个分区的副本分散到不同机架。

  1. 核对可靠性配置。检查 topic 的副本因子、min.insync.replicas、unclean.leader.election.enable、保留策略和清理策略,以及生产者的 acks、重试和幂等配置。若某分区的 ISR 已经等于 min.insync.replicas,再停一台 broker 就可能让该分区拒绝写入,必须先把副本补齐或调整迁移顺序。不要为了迁移方便关闭 acks=all、降低 min.insync.replicas 或开启不安全的 leader 选举。

  2. 确认 controller 选举风险。KRaft 模式下替换 controller 要逐个进行:先让新 controller 加入 quorum 并追平元数据,再移除旧成员,任何时刻都不能同时失去多数派。ZooKeeper 模式下 controller 由 broker 选举产生,替换当前 controller 前先确认 ZooKeeper 健康,并接受一次短暂的 controller 切换。

  3. 盘点客户端和入口。确认 bootstrap 列表包含多个可用 broker,客户端能刷新元数据;检查 DNS、负载均衡、防火墙、advertised.listeners 和机架配置。生产者、消费者、Connect、MirrorMaker、Schema Registry 和监控都可能固定连接某个 broker,迁移后要验证它们能重新发现集群。

  4. 导出元数据并准备回滚。记录 topic 描述、配置、ACL、消费者组位点、分区分配和当前 reassignment 状态。保留旧 broker 的数据目录和配置,在替换完成并观察稳定前不要删除。回滚通常只能回到旧节点仍持有完整数据的时点;如果数据已经迁移并被新写入覆盖,回滚应按一次新的迁移重新评估。

  5. 约定维护窗口、限速和验收标准。暂停自动均衡、定时重分配和其他会移动副本的任务,通知业务方。准备限速值、单批分区数、成功标准(ISR 恢复、无离线分区、生产消费正常)和停止条件(ISR 持续不足、磁盘或网络打满、controller 抖动)。

操作步骤

1. 固定基线

记录集群 ID、controller 状态、broker 列表、topic 分配、ISR、消费者 lag 和磁盘水位,作为迁移后的对照:

kafka-metadata-quorum.sh --bootstrap-server "$BS" describe --status > /backup/quorum-before.txt
kafka-topics.sh --bootstrap-server "$BS" --describe > /backup/topics-before.txt
kafka-consumer-groups.sh --bootstrap-server "$BS" --describe --all-groups > /backup/groups-before.txt

2. 选择替换方式

常见做法有三种。第一,使用原 node ID 启动一个空日志目录的新 broker,让它重新拉取分配给自己的副本;这种方式对客户端和元数据最透明,但要确认元数据模式支持该节点身份,且旧进程已经停止,不能与新进程同时使用同一 ID。第二,使用新 node ID 加入集群,再通过分区重分配把副本迁走,最后退役旧节点;步骤更清晰,适合跨机型或跨机架迁移。第三,先扩容新 broker,再缩容旧 broker,适合需要保持容量不变的场景。

无论选哪种,都要先在测试集群验证加入、同步、重分配和移除流程。不要复制另一个 broker 的日志目录来“克隆”节点,也不要把不同 cluster ID 的数据目录混在一起。

3. 准备并加入新 broker

新节点应使用匹配的 Kafka 版本、相近的 CPU、内存、磁盘和网络配置,设置唯一的 node ID、正确的 listeners 与 advertised.listeners、机架信息和独立日志目录,并接入监控、日志、时间同步和备份。KRaft 节点必须使用原 cluster ID 和正确的 controller quorum 配置,不能格式化成新集群。

启动后确认 broker 已注册、没有重复 ID、日志目录可写、副本开始拉取。观察网络和磁盘是否在可接受范围,再进入重分配。

4. 迁移分区副本

先用工具生成迁移计划,保存原始分配,再逐步执行。--generate 的输出同时包含“当前分配”和“建议分配”两段带标题的 JSON,不能把整段 stdout 直接当作重分配文件;应只提取建议分配那一段。不要让一次重分配覆盖全部分区,也不要把同一分区的多个副本同时移走:

kafka-reassign-partitions.sh --bootstrap-server "$BS" \
  --generate --topics-to-move-json-file topics.json \
  --broker-list <new-broker-ids> > reassignment-plan.txt
awk '/Proposed partition reassignment configuration/{found=1; next} found{print}' \
  reassignment-plan.txt > reassignment.json
kafka-reassign-partitions.sh --bootstrap-server "$BS" \
  --reassignment-json-file reassignment.json --execute --throttle <bytes-per-second>
kafka-reassign-partitions.sh --bootstrap-server "$BS" \
  --reassignment-json-file reassignment.json --verify

执行期间持续观察 ISR、离线分区、磁盘、网络和 controller 日志。若 ISR 掉到 min.insync.replicas 以下,停止后续批次,先恢复副本冗余;只有在当前版本支持时才取消本次重分配,不要通过降低 min.insync.replicas 或关闭 acks=all 让写入“恢复”。重分配完成后,用 preferred leader election 把 leader 逐步迁回合适节点,但必须等 ISR 完整后再执行。

5. 退役旧 broker

确认旧 broker 上已经没有需要保留的分区副本,再执行受控停止。停止前检查是否有正在进行的重分配、是否有分区 leader 位于该节点、是否还有客户端固定连接。停止后等待 ISR 恢复,确认没有离线分区,再把节点从 bootstrap 列表、DNS、监控和自动化配置中移除。

如果旧节点是 controller,先完成 controller 成员替换并确认 quorum 稳定,再停止 broker 角色。KRaft 的 controller 移除要使用对应版本的官方工具,逐台确认 voter 数量和 active controller;ZooKeeper 模式接受一次自动 controller 选举,但要避免同时重启多个 broker。

6. 收尾与客户端切换

更新客户端 bootstrap 列表和 DNS,滚动重启或让客户端刷新元数据,验证生产者、消费者、Connect、MirrorMaker 和 Schema Registry。恢复自动均衡和定时任务,移除重分配限速,更新容量台账和拓扑文档。旧数据目录至少保留一个回滚窗口,确认新节点稳定、备份完成后再按流程销毁。

验证

失败与回滚

新 broker 无法加入。 检查 cluster ID、node ID、controller quorum 配置、advertised.listeners、日志目录权限和版本兼容性。不要格式化旧的元数据目录,也不要用相同 node ID 同时启动两个进程。

重分配卡住或 ISR 不足。 降低限速或停止后续批次,检查网络、磁盘 I/O、副本拉取配置和 broker 负载;先恢复副本冗余,再继续。只有在版本支持时才能取消本次重分配;不要删除旧 broker 的数据目录,也不要在 ISR 不足时执行不安全的 leader 选举。

controller 失去多数派。 立即停止后续变更,恢复故障 controller 或网络,确认 quorum 后继续。不能用强制手段制造第二个 active controller;如果元数据已经损坏,应按整集群恢复流程处理。

出现数据丢失。 确认是否有副本被 unclean 选举为 leader,检查生产者和消费者的 offset,评估丢失窗口。优先从健康副本、备份或上游数据重放恢复,并向业务方明确 RPO,不要用“集群已恢复”掩盖数据缺口。

需要回滚。 如果旧 broker 的数据目录仍完整且新节点尚未承接大量写入,可以停止新节点、恢复旧节点身份和配置,再把客户端切回;切换前确认没有两个节点同时使用同一 ID。若数据已经迁移并被新写入覆盖,回滚应作为一次新的迁移重新规划,保留双方数据并核对 offset。

相关命令

参考链接

读完自测

合上页面,先回答,再展开对照。

  1. 替换 broker 前,为什么要先看 min.insync.replicas 和当前 ISR?
  2. KRaft 模式下替换 controller 时,最重要的安全边界是什么?
  3. 分区重分配之后,为什么不能立刻删除旧 broker 的数据目录?
答案
  1. 如果某个分区的 ISR 已经等于 min.insync.replicas,再停掉一台 broker 就可能让该分区无法满足写入确认条件,生产会失败。应先补齐副本、调整迁移顺序,不能通过降低 min.insync.replicas 或关闭 acks=all 绕过。
  2. 任何时刻都必须保住 controller quorum 的多数派。新 controller 要先加入并追平元数据,再移除旧成员,逐台进行;同时失去多数派会导致元数据无法提交,不能靠强制手段制造第二个 active controller。
  3. 旧目录是回滚和排查的最后依据。重分配完成不代表新副本已经稳定,客户端、备份和监控也可能尚未收敛;保留旧目录直到新节点通过验证和回滚窗口,才能避免把唯一可用数据删掉。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令