如果单台Broker的磁盘即将打满,如何在不停机的情况下安全地将部分Partition迁移到其他Broker上?
在Kafka集群中,单台Broker磁盘即将打满是一个常见的生产紧急情况。Kafka原生支持在不停机、不影响客户端读写的情况下,通过副本迁移(Partition Reassignment)来平衡磁盘空间。
以下是安全、平滑地将部分Partition迁移到其他Broker的标准操作流程(SOP):
第一阶段:紧急缓解(可选,争取时间)
在做数据迁移前,如果磁盘已经到达95%以上,随时可能宕机,建议先执行以下操作争取时间:
- 临时缩短该Broker上大Topic的保留时间(Retention):注:这会让Kafka立刻清理过期数据,释放空间。迁移完成后可改回原值。bash
kafka-configs.sh --bootstrap-server <broker-list> --entity-type topics --entity-name <heavy-topic> --alter --add-config retention.ms=86400000
第二阶段:精准定位与计划
不要盲目迁移整个Topic,只迁移占用空间最大的几个Partition。
1. 找出占用空间最大的Partition
登录磁盘告警的Broker,进入Kafka的 log.dirs 目录,找出最大的文件夹:
du -sh * | sort -hr | head -n 10
假设找到占用最大的是 order-events-2(Topic为order-events,Partition 2),当前在 Broker 1(即将满的机器)上。
2. 确定目标 Broker
查看集群中其他Broker的磁盘空间,挑选1~2台空间充足的Broker(假设挑选了 Broker 2 和 Broker 3)。
第三阶段:手工编写迁移计划(最精准安全的方式)
使用Kafka自带的 kafka-reassign-partitions.sh 工具。为了精准控制,我们手动编写重分配的JSON文件,而不是让Kafka自动生成。
创建一个 reassign.json 文件:
{
"version": 1,
"partitions": [
{
"topic": "order-events",
"partition": 2,
"replicas": [2, 3],
"log_dirs": ["any", "any"]
}
]
}
- 解释:上述JSON告诉Kafka,将
order-events的partition 2的副本迁移到 Broker 2 和 Broker 3 上(从而将其从 Broker 1 上移走)。 - 安全建议:一次不要迁移太多,建议每次只迁移 1~3 个大的Partition,分批进行。
第四阶段:执行限流迁移(保证不停机的关键)
如果不限流,底层大量复制数据会打满网卡和磁盘IO,导致Broker假死、Leader选举超时,从而引起停机。
1. 执行迁移并设置限流(Throttle)
使用 --throttle 参数限制复制速度(单位是 Bytes/sec)。例如限制为 50MB/s(50000000):
kafka-reassign-partitions.sh --bootstrap-server <broker-list> \
--reassignment-json-file reassign.json \
--execute \
--throttle 50000000
执行后,Kafka会输出一段当前的副本分配状态(Current partition replica assignment),请务必将这段JSON保存下来,以便出现意外时可以回滚。
第五阶段:监控与验证
1. 查看迁移进度
kafka-reassign-partitions.sh --bootstrap-server <broker-list> \
--reassignment-json-file reassign.json \
--verify
你会看到类似 is still in progress(正在进行)或 completed successfully(已完成)的提示。
2. 观察磁盘空间
- 目标Broker的磁盘空间会逐渐增加。
- 注意:源Broker(Broker 1)的磁盘空间不会立刻减少。Kafka的机制是:先在目标Broker创建新副本 -> 复制数据 -> 追上进度成为ISR -> 发生Leader切换 -> 最后才会删除旧Broker上的副本。当看到Broker 1磁盘空间突然下降时,说明该Partition迁移彻底完成了。
第六阶段:清理限流(极其重要!)
迁移完成后(--verify 显示全部成功),必须移除限流配置。如果不移除,未来该Topic正常的副本同步也会受到这个速度限制,非常危险。
重新运行一遍没有 --throttle 的 --verify 命令,或者显式清理:
kafka-configs.sh --bootstrap-server <broker-list> --entity-type brokers --entity-default --alter --delete-config leader.replication.throttled.rate,follower.replication.throttled.rate
kafka-configs.sh --bootstrap-server <broker-list> --entity-type topics --entity-name order-events --alter --delete-config leader.replication.throttled.replicas,follower.replication.throttled.replicas
💡 高级技巧与注意事项
单机多磁盘(JBOD)迁移方案:
如果你的单台Broker挂载了多块磁盘(log.dirs配置了多个路径),并且只是其中一块磁盘满了。从 Kafka 1.1.0 开始,支持Broker内部磁盘间迁移。
只需在编写JSON时,利用log_dirs属性指定目标磁盘路径的绝对目录即可,无需跨网络传输,速度极快且不消耗网络带宽。客户端完全无感吗?
是的。Kafka在迁移完成的最后一刻,会自动进行Leader切换。客户端(Producer/Consumer)通过定期拉取Metadata感知到Leader变化,会自动重连到新的Broker上,会有毫秒级的延迟,但不会报错或停机。避开高峰期:
尽管做了限流,依然建议在业务低谷期(如凌晨)进行此类运维操作,将风险降到最低。