Kafka 没有 etcd 那种内置的一致性快照命令。这里说的“快照”是文件系统、云盘或存储层快照,必须与 broker 停机或文件系统冻结配合;在线直接复制 log.dirs 可能得到撕裂的日志段和索引。更常见的恢复路径不是恢复快照,而是利用副本重建;只有副本全部丢失、元数据损坏或需要回到历史时点时才使用快照。
本流程的 RPO 由最后一次可用副本或快照决定。Kafka 不是事务数据库,恢复后通常只能保证“至少一次”,消费者必须能处理重复消息。
kafka-topics.sh --bootstrap-server "$BS" --describe --under-replicated-partitions
kafka-metadata-quorum.sh --bootstrap-server "$BS" describe --status
kafka-log-dirs.sh --bootstrap-server "$BS" --describe
记录哪些 broker 在线、哪些分区没有 leader、哪些分区 ISR 不足,以及 controller quorum 是否仍然存在。如果还有一份完整的同步副本,优先修复 broker 和副本,不要用快照覆盖健康数据。
kafka-topics.sh --bootstrap-server "$BS" --list > topics.txt
while read -r t; do
kafka-topics.sh --bootstrap-server "$BS" --describe --topic "$t"
done < topics.txt > topics-describe.txt
while read -r t; do
kafka-configs.sh --bootstrap-server "$BS" \
--describe --entity-type topics --entity-name "$t"
done < topics.txt > topic-configs.txt
kafka-acls.sh --bootstrap-server "$BS" --list > acls.txt
kafka-consumer-groups.sh --bootstrap-server "$BS" --list > groups.txt
清单要包含分区数、副本因子、min.insync.replicas、保留策略、清理策略、压缩方式和消息大小限制。恢复时不能依赖自动建 topic,否则分区数和副本因子通常不符合生产要求。
kafka-get-offsets.sh --bootstrap-server "$BS" --topic orders --time -1
如果快照是存储层打出的,记录快照 ID、拍摄时间、所有 broker 的 node ID、KRaft cluster ID 和 metadata.log.dir。只恢复数据日志、不恢复元数据日志,可能得到一个无法加入 quorum 的集群。
确认快照一致性和容量。快照必须覆盖所有相关 broker 的 log.dirs 与 KRaft 元数据目录;在线快照要确认存储层支持多卷一致性,或已经停止 broker。检查目标磁盘空间、文件权限、时间同步,以及目标环境的 listeners 和 advertised.listeners 是否能被客户端访问。
冻结生产者和消费者,停止消费者组。消费者仍在运行时,offset 会继续变化,无法判断恢复后从哪里继续;关闭自动提交后,仍可能有已处理未提交的消息,要按业务幂等性处理。
停止所有 broker 和 controller,保留旧数据目录、日志和快照。不要在未确认快照一致性的情况下直接覆盖生产 log.dirs,也不要把新旧日志目录混在一起启动。
如果是单 broker 故障且集群仍有 quorum,不要进入整集群恢复:把故障节点的数据目录移走,保留空目录和原 node ID,启动进程让副本重新同步。
元数据和数据必须成对。若元数据日志完好,直接恢复数据目录后检查 topic 描述,不要重建同名 topic;若元数据丢失,按导出的清单重建 topic、配置和 ACL:
kafka-topics.sh --bootstrap-server "$BS" --create \
--topic orders \
--partitions 12 \
--replication-factor 3 \
--config min.insync.replicas=2 \
--config cleanup.policy=delete \
--config retention.ms=604800000
分区数只能增加不能减少,恢复时应使用原分区数;副本因子不能超过目标 broker 数。ACL、SCRAM 凭据、配额和 topic 配置要单独恢复,不能只创建 topic 名称。内部 topic 如 __consumer_offsets、__transaction_state 不应手工随意重建,优先随快照恢复或让集群按配置自动创建。
副本重建。 启动一个空日志目录的 broker,使用原 node ID 加入集群,让它从 leader 拉取分区副本。如果原节点无法恢复,用新 node ID 替换,并通过分区重分配把副本迁走:
kafka-reassign-partitions.sh --bootstrap-server "$BS" \
--reassignment-json-file plan.json --execute
kafka-reassign-partitions.sh --bootstrap-server "$BS" \
--reassignment-json-file plan.json --verify
重分配前先用 --generate(需同时提供 --topics-to-move-json-file 与 --broker-list)生成 plan.json,确认分区数不变,再执行并 verify。重分配会消耗大量磁盘和网络 I/O,应避开业务高峰,并一次只处理有限分区。不要为了追求速度把 unclean.leader.election.enable 设为 true,否则可能把未同步的副本选为 leader,直接丢数据。
快照恢复。 停止所有 broker 和 controller,把同一时点的快照恢复到各自节点;恢复 log.dirs 和 KRaft 元数据日志,核对 cluster ID、node ID、目录权限和配置文件。角色分离时先让 controller quorum 形成,再启动 broker;合并角色按节点配置启动。不要对恢复出来的元数据目录执行格式化,也不要把不同节点、不同快照的数据目录拼在一起。
重建加回放。 如果快照不可用,创建新集群,按清单重建 topic,再从上游 CDC、对象存储或业务补偿日志重放。重放前确认消费者幂等、消息键和分区路由不会改变顺序;这条路径无法保证零丢失,必须由业务确认 RPO。
如果 __consumer_offsets 随快照一起恢复,消费组通常会回到快照时点的提交位置。若 offset 丢失、指向已过期数据,或恢复后的日志终点早于已提交 offset,就要重置。先停止消费者,确认组内没有 active member:
kafka-consumer-groups.sh --bootstrap-server "$BS" --describe --group order-svc
kafka-consumer-groups.sh --bootstrap-server "$BS" --group order-svc \
--topic orders --reset-offsets \
--to-datetime 2026-10-18T02:30:00.000+08:00 --dry-run
确认结果后把 --dry-run 改成 --execute。重置到 earliest 会重复消费,重置到 latest 会跳过中间数据;选择哪一种取决于业务是否幂等、能否接受重复以及是否必须补齐历史。不要在没有 dry-run 和备份 offset 的情况下批量重置全部消费组。
UnderReplicatedPartitions 为 0,ISR 数量等于副本因子。kafka-topics.sh --describe 中的分区数、副本因子、leader 和配置与清单一致,没有意外自动创建的 topic。kafka-get-offsets.sh 的分区终点与快照记录或恢复目标一致;抽查消息键、时间戳和内容,确认没有跨分区错位。__consumer_offsets、__transaction_state 等内部 topic 的副本和 ISR 正常;使用事务消息时,read_committed 消费者能正常读到已提交数据。broker 无法启动。 先看日志中的 cluster ID、node ID、元数据日志和 log.dirs 错误。不要用格式化命令“修复”元数据目录;格式化会生成新的 cluster ID,原有数据将无法加入。确认恢复目录的属主、磁盘挂载和配置文件与目标节点匹配。
ISR 长期不足。 检查副本拉取网络、磁盘 I/O、replica.fetch.max.bytes 和 ISR 超时配置。先让 broker 稳定运行,再做分区重分配;不要在副本未同步时删除 leader 或执行不安全的 leader 选举。
快照数据不一致。 立即停止所有 broker,保留失败目录和日志,重新从上一份通过校验的快照恢复全部节点。不能只替换某个节点的日志,也不能把旧目录中“看起来完整”的分区拼回新快照。
消费者位点错误。 停止消费组,记录当前 offset 和业务处理进度,再用 dry-run 确认重置目标。无法确定时宁可回到 earliest 配合幂等消费,也不要直接跳到 latest 造成静默漏数。
无法恢复原集群。 新建集群、重建元数据并从上游重放,明确记录丢失的时间窗口。不要让旧集群继续接受写入后再切回,否则两个集群的 offset 和业务状态无法对齐。
需要回滚。 在客户端切换前,保留旧集群和旧数据目录;若新集群验证失败,停止新集群写入,隔离网络,再把客户端切回仍一致的旧集群。若旧集群已经落后,先核对差异并补偿,不能简单改 DNS 了事。
合上页面,先回答,再展开对照。
kafka-consumer-groups.sh --reset-offsets 先 dry-run 再执行,选择 earliest 或目标时间;不能直接跳到 latest,否则会静默漏数。
小程序版
微信扫码,随时查命令