最近有一件比较糟心的事就是出于公司业务需要将某云上一台服务器更换到另外一台服务器上。虽然个人不太赞同这样的做法,毕竟风险太大,收益太小,但是公司有自身的商务和战略上的考虑。另外未来确实有更换大容量服务器节点的需求存在,这也是一次比较好的演练的机会。
比较不幸的事,该服务器上存着mysql的数据备份,zookeeper集群节点以及kafka集群节点。周末晚上几经折腾终于完成kafka集群节点的迁移更换,中间踩了好几次坑,血淋淋的教训,确实需要记录一下。
迁移的坑
迁移节点,忘了数据
在前期调研准备kafka集群节点迁移更换方案后,自以为是的以为只要布置了新节点,并且停止旧节点,kafka集群能够自动在新节点上恢复备份数据。现实就是然并卵。Kafka并不会在新节点上自动回复节点数据,至少kafka-2.6.0并不会。所以还需要迁移旧节点数据到新的节点上。
迁移数据,但没有迁全
另外一个坑就是,迁移kafka节点上的topic数据的时候,仅迁移了业务需要的topic数据而没有迁移kafka本身的需要的内建topic,导致kafka无法正常运作。这个坑更加隐蔽,而且网上没有什么资料,关键是kafka集群本身甚至不会给出错误日志。
前期准备工作
在kafka集群节点迁移更换以前,需要做一些准备工作。主要是两点,首先需要布置运行新的节点加入到集群中。然后需要了解所有topic在kafka旧节点即kafka的broker上的分布情况。然后根据掌握到的信息,制定迁移策略。
布置运行新的kafka节点
布置新的kafka节点可以参考小白以前写的文章:小白7码-拾遗笔记-弃坑rocketMQ,入坑kafka之基于openjdk的消息队列选择。特别需要注意的是三个方面。首先需要给kafka的运行脚本kafka-run-class.sh指定JAVA_HOME,特别是你在服务上以非root账号运行程序的时候。其次是要给kafka配置账号密码权限访问,需要配置kafka_server_jaas.conf和server.properties,并且要在kafka-server-start.sh指定账号密码权限访问。最后,需要给新的节点配置唯一的server.id,避免和旧节点冲突。
当前Topic及其Partition的节点分布
在新的kafka节点即新的broker运行起来后,需要了解节点中现有的Topic及其Partition的分布情况。根据现有的Topic及其Partition的分布情况可以了解哪些Topic和它的Partition需要迁移到新的kafka节点。
首先在kafka安装目录的bin目录下,找到kafka-topics.sh脚本文件,并运行下面的脚本:
./kafka-topics.sh --zookeeper {zookeeper ip地址和端口列表} –describe
然后我们就可以获取到各个topic及其partition在kafka集群节点上的分布明细,具体的例子如下:
图表 1 Topic及其partition的分布
需要注意其中四个数据:Topic,Partition,Replicas以及__consumer_offsets。
Topic就是kafka中的topic。而每个Topic至少有一个Partition,每个Partition通常对应的一个队列数据文件,而对应的队列数据文件分布在哪个kafka的节点,可以通过Replicas数据确定。例如Replicas是1,通常表示该Partition在broker 1上即在server.id = 1的Kafka节点上。而__consumer_offsets是特殊的Topic,它是kafka用来记录Topic的数据消费的位移数据。
节点迁移更换
节点迁移的主要工作就是将旧节点上的相关topic的partition数据迁移到新的节点上。需要用到kafka的kafka-reassign-partitions.sh脚本工具。kafka-reassign-partitions.sh脚本既可以提供数据迁移的推荐方案,又可以执行数据迁移。
生成数据迁移推荐方案
前面我们已经收集到topic及其partition的分布情况,根据分布情况,我们可以确定我们需要迁移的目标topic。将需要迁移的目标通过类似下面的文件格式,整理成一个json文件:
{
"topics":[
{
"topic":"__consumer_offsets"
}
],
"version":1
}
然后通过kafka-reassign-partitions.sh脚本使用下面的命令生成数据迁移推荐方案,例如需要把broker 0上的__consumer_offsets迁移到broker 1上:
./kafka-reassign-partitions.sh --zookeeper {zookeeper
ip地址和端口列表} --generate --topics-to-move-json-file {上面整理的json文件}.json --broker-list 1
然后我们就可以获得迁移推荐方案:
图表 2 kafka迁移推荐方案
kafka-reassign-partitions.sh脚本会给出现在的分配情况,同时在下面给出推荐的重分配方案,需要分配的目标可以通过--broker-list选项指定。最后我们需要上面的重分配方案保存成一个json文件。
执行数据迁移方案
生成数据迁移的推荐方案并不会执行该方案,这一步类似检查确认的环节。需要让数据迁移方案真正执行生效,需要通过kafka-reassign-partitions.sh脚本执行下面的命令:
./kafka-reassign-partitions.sh --zookeeper {zookeeper
ip地址和端口列表} --execute --reassignment-json-file {整理保存的重分配方案文件}.json
执行成功后,需要通过topic脚本再次确认数据迁移结果:
./kafka-topics.sh --zookeeper {zookeeper ip地址和端口列表} –describe
停止旧节点
上述工作完成后,我们可以先测试一下自己的程序通过新的节点是否可以正常通信。如果没有问题,就可以通过kafka-server-stop.sh脚本停止旧节点。并在此测试自己的程序是否能够正常通信。
结论
到这里,我们已经顺利完成kafka节点的迁移更换。最后,有几点需要特别注意。第一,小白使用的是kafka-2.6.0的古董版本,后续版本—-zookeeper选项会被取消,所以请调整对应的命令,可能需要使用—-bootstrap-server替代。另外,数据迁移的时候,特别需要注意将__consumer_offsets这个特殊的topic一起迁移。如果遗漏会导致数据队列无法正常工作。猜测可能的原因是消费端请求的时候,kafka不能找到正确的消费位置偏移导致的。