很多接触过Kafka集群维护的开发者,都遇到过节点要下线的情况。要是操作不对,轻则业务延迟飙升,重则数据读写失败,整个服务挂掉都有可能。今天就聊一聊Kafka节点下线时的那些坑,以及怎么一步步平滑操作,避免踩坑。

一、Kafka节点下线的常见坑点

1.1 直接关节点导致分区不可用

很多新手的第一反应是“节点不用了,直接关机就行”,但Kafka的每个分区都有多个副本存放在不同节点上,要是某个分区的最后一个副本在要下线的节点上,直接关节点会让这个分区失去所有备份,变成不可用状态——生产者写不进数据,消费者也读不出来,这在生产环境里绝对是大事故。我朋友上个月就踩过这个坑,直接关了要下线的节点,导致12个分区全挂了,折腾了3小时才恢复。

1.2 盲目迁移导致业务性能下降

有的开发者知道要迁移副本,但一次性把几百个分区的副本同时迁走,会占用集群大量带宽和磁盘IO,导致整个Kafka集群的请求响应变慢,消费者延迟飙高,业务出现明显卡顿,尤其是数据量比较大的分区,比如单个分区有几个G甚至几十个G的情况,影响会更明显。

二、平滑下线的前置准备

2.1 查清楚要下线的节点有哪些分区

在动手操作前,得先明确这个节点上到底跑了多少分区,这些分区的副本都存在哪里,有没有最后一个副本的分区。用Kafka自带的脚本就能查,非常简单:

# 替换成你自己的Kafka集群地址,比如192.168.1.100:9092,再把1001改成要下线的Broker ID
kafka-topics.sh --describe --bootstrap-server 你的Kafka地址:9092 | grep "Leader: 1001"

这个命令会把所有以1001为Leader的分区都列出来,要是你看到某个分区的Replicas(副本)列表里只有1001,那这个分区就是只有这个节点存数据,绝对不能直接关。

2.2 选对操作时机

别在业务高峰时操作,比如电商的618、凌晨的业务峰值之后,选用户少、流量低的时间段,比如凌晨2点到4点,这时候即使有轻微的性能波动,对业务也不会有太大影响。

2.3 确认集群存活状态

先确认要下线的节点不是最后一个存活的节点,也不是集群的核心节点(比如Controller节点),可以用这个命令看看所有节点的状态:

# 查看所有Broker的ID和存活状态,去掉dead的节点
kafka-broker-api-versions.sh --bootstrap-server 你的Kafka地址:9092

三、平滑下线的具体操作步骤

3.1 生成合理的副本迁移计划

迁移副本不能随便改,得保证每个分区的副本数不变,而且新的副本节点是存活的。我们用kafka-reassign-partitions.sh脚本生成迁移计划,举个例子,假设要把Broker 1001上的分区移到1002和1003节点上,先创建一个JSON文件:

# 创建并编辑迁移计划文件,替换成自己的topic和Broker ID
cat > reassign-plan.json << EOF
{
  "version":1,
  "partitions":[
    # 把topic为"订单日志"的第0个分区,原来的副本是[1001,1002],改成[1002,1003],去掉1001
    {"topic":"订单日志","partition":0,"replicas":[1002,1003]},
    # 把topic为"用户行为"的第2个分区,原来的副本是[1001,1002],改成[1002,1003],去掉1001
    {"topic":"用户行为","partition":2,"replicas":[1002,1003]},
    # 其他分区同理,都要去掉要下线的Broker ID
    {"topic":"商品点击","partition":5,"replicas":[1002,1003]}
  ]
}
EOF

这里要注意,别把副本数改少,比如原来2个副本,不能改成1个,不然会有数据丢失的风险。

3.2 执行迁移计划

生成好计划后,就可以执行迁移了,这个命令会启动副本迁移:

# 执行迁移,注意替换成自己的Kafka地址和计划文件名
kafka-reassign-partitions.sh --bootstrap-server 你的Kafka地址:9092 --reassignment-json-file reassign-plan.json --execute

3.3 监控迁移进度,直到完成

迁移不是瞬间完成的,尤其是大分区,得等进度跑完,用这个命令检查:

# 查看迁移状态,直到所有分区的status变成"Completed"
kafka-reassign-partitions.sh --bootstrap-server 你的Kafka地址:9092 --reassignment-json-file reassign-plan.json --verify

要是看到有分区的status是"InProgress",就再等一会,别着急关机,等所有迁移完成再进行下一步。

3.4 关闭要下线的节点

确认所有分区都迁移完成后,就可以安全关闭节点了,这时候这个节点上已经没有任何分区的副本,关掉不会影响业务。

四、平滑下线的关键注意事项

4.1 别同时下线多个节点

一次只处理一个节点,要是同时下线两三个,集群会忙不过来,可能导致分区不可用或者延迟飙升,一定要一个一个来,等第一个节点下线确认没问题,再处理下一个。

4.2 控制迁移的速度

要是集群数据量很大,一次性迁移太多分区会占满带宽,这时候可以加限速参数,限制每秒迁移的数据量,比如限速100MB:

# 执行迁移时加限速参数,单位是字节,100MB就是100*1024*1024=104857600
kafka-reassign-partitions.sh --bootstrap-server 你的Kafka地址:9092 --reassignment-json-file reassign-plan.json --execute --throttle 104857600

这样就能避免迁移时把集群带宽占满,影响业务的正常请求。

4.3 迁移时观察业务指标

迁移过程中要盯着几个关键指标:生产者的请求延迟、消费者的堆积数、集群的CPU和IO使用率,要是出现异常波动,就暂停一下迁移,等业务平稳了再继续,比如分批次迁移,每次迁50个分区,休息10分钟。

五、常见坑点的详细分析

5.1 坑点1:迁移计划写错导致失败

比如不小心把副本列表写成了不存在的Broker ID,或者把副本数改少了,执行迁移时会报错,这时候得重新生成正确的计划,再重新执行。比如有人把[1002,1003]写成[1004,1005],要是这两个Broker不存在,迁移肯定失败,就得改回来。

5.2 坑点2:忽略副本数,导致分区变成单副本

要是某个分区的副本数本来是2,迁移时不小心改成1,那这个分区就只有一个副本,要是再关其他节点,这个分区就会不可用,所以生成计划的时候一定要核对每个分区的副本数和原副本数一致。

5.3 坑点3:迁完成就关节点,没验证

刚才说的迁移状态要等所有完成,要是提前关节点,可能还有少量分区没迁完,这时候关掉会导致这些分区的数据丢失,必须等verify确认所有都完成再关。

六、总结

Kafka节点下线的核心是“先迁副本,后关节点”,别嫌麻烦,一定要按步骤来,别图快直接关机。要是你是刚接触Kafka的开发者,或者平时很少运维集群,一定要在测试环境先练几次,熟悉命令和流程,等熟练了再碰生产环境。生产环境操作前,最好跟团队里的人说一声,或者留好备份,出问题也能快速恢复。