版本信息最后核对:2026-10-25
先区分“替换 broker”和“重建副本”。替换只是把进程或主机换掉,分区数据仍由其他副本提供;如果某个分区只剩一份副本,替换前必须先确认这份数据可用并完成备份,否则重启或迁移都可能造成不可恢复的丢失。还要确认集群的元数据模式:KRaft 使用 controller quorum,ZooKeeper 使用独立或合并的 controller 选举,两者的替换步骤和风险边界不同。
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 前,必须保证剩余节点仍能形成多数派。
kafka-log-dirs.sh --bootstrap-server "$BS" --describe
kafka-topics.sh --bootstrap-server "$BS" --describe
kafka-consumer-groups.sh --bootstrap-server "$BS" --list
同时检查机架感知配置。如果副本都集中在同一机架,单机架故障仍可能丢数据;迁移计划应让每个分区的副本分散到不同机架。
核对可靠性配置。检查 topic 的副本因子、min.insync.replicas、unclean.leader.election.enable、保留策略和清理策略,以及生产者的 acks、重试和幂等配置。若某分区的 ISR 已经等于 min.insync.replicas,再停一台 broker 就可能让该分区拒绝写入,必须先把副本补齐或调整迁移顺序。不要为了迁移方便关闭 acks=all、降低 min.insync.replicas 或开启不安全的 leader 选举。
确认 controller 选举风险。KRaft 模式下替换 controller 要逐个进行:先让新 controller 加入 quorum 并追平元数据,再移除旧成员,任何时刻都不能同时失去多数派。ZooKeeper 模式下 controller 由 broker 选举产生,替换当前 controller 前先确认 ZooKeeper 健康,并接受一次短暂的 controller 切换。
盘点客户端和入口。确认 bootstrap 列表包含多个可用 broker,客户端能刷新元数据;检查 DNS、负载均衡、防火墙、advertised.listeners 和机架配置。生产者、消费者、Connect、MirrorMaker、Schema Registry 和监控都可能固定连接某个 broker,迁移后要验证它们能重新发现集群。
导出元数据并准备回滚。记录 topic 描述、配置、ACL、消费者组位点、分区分配和当前 reassignment 状态。保留旧 broker 的数据目录和配置,在替换完成并观察稳定前不要删除。回滚通常只能回到旧节点仍持有完整数据的时点;如果数据已经迁移并被新写入覆盖,回滚应按一次新的迁移重新评估。
约定维护窗口、限速和验收标准。暂停自动均衡、定时重分配和其他会移动副本的任务,通知业务方。准备限速值、单批分区数、成功标准(ISR 恢复、无离线分区、生产消费正常)和停止条件(ISR 持续不足、磁盘或网络打满、controller 抖动)。
记录集群 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
常见做法有三种。第一,使用原 node ID 启动一个空日志目录的新 broker,让它重新拉取分配给自己的副本;这种方式对客户端和元数据最透明,但要确认元数据模式支持该节点身份,且旧进程已经停止,不能与新进程同时使用同一 ID。第二,使用新 node ID 加入集群,再通过分区重分配把副本迁走,最后退役旧节点;步骤更清晰,适合跨机型或跨机架迁移。第三,先扩容新 broker,再缩容旧 broker,适合需要保持容量不变的场景。
无论选哪种,都要先在测试集群验证加入、同步、重分配和移除流程。不要复制另一个 broker 的日志目录来“克隆”节点,也不要把不同 cluster ID 的数据目录混在一起。
新节点应使用匹配的 Kafka 版本、相近的 CPU、内存、磁盘和网络配置,设置唯一的 node ID、正确的 listeners 与 advertised.listeners、机架信息和独立日志目录,并接入监控、日志、时间同步和备份。KRaft 节点必须使用原 cluster ID 和正确的 controller quorum 配置,不能格式化成新集群。
启动后确认 broker 已注册、没有重复 ID、日志目录可写、副本开始拉取。观察网络和磁盘是否在可接受范围,再进入重分配。
先用工具生成迁移计划,保存原始分配,再逐步执行。--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 完整后再执行。
确认旧 broker 上已经没有需要保留的分区副本,再执行受控停止。停止前检查是否有正在进行的重分配、是否有分区 leader 位于该节点、是否还有客户端固定连接。停止后等待 ISR 恢复,确认没有离线分区,再把节点从 bootstrap 列表、DNS、监控和自动化配置中移除。
如果旧节点是 controller,先完成 controller 成员替换并确认 quorum 稳定,再停止 broker 角色。KRaft 的 controller 移除要使用对应版本的官方工具,逐台确认 voter 数量和 active controller;ZooKeeper 模式接受一次自动 controller 选举,但要避免同时重启多个 broker。
更新客户端 bootstrap 列表和 DNS,滚动重启或让客户端刷新元数据,验证生产者、消费者、Connect、MirrorMaker 和 Schema Registry。恢复自动均衡和定时任务,移除重分配限速,更新容量台账和拓扑文档。旧数据目录至少保留一个回滚窗口,确认新节点稳定、备份完成后再按流程销毁。
UnderReplicatedPartitions 回到零,ISR 数量等于副本因子,min.insync.replicas 得到满足。acks=all 的生产者可以持续写入,消费者 lag 稳定,没有反复 rebalance;事务消息使用 read_committed 时也能正常读取。新 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。
合上页面,先回答,再展开对照。
min.insync.replicas 和当前 ISR?min.insync.replicas,再停掉一台 broker 就可能让该分区无法满足写入确认条件,生产会失败。应先补齐副本、调整迁移顺序,不能通过降低 min.insync.replicas 或关闭 acks=all 绕过。
小程序版
微信扫码,随时查命令