本文參考了網上部分文章,並進行了說明和歸納,詳情請查看參考。
官方文檔參考:https://cwiki.apache.org/confluence/display/KAFKA/Replication+tools
kafka環境中機器磁盤告警很容易出現,原因可能是某一個topic
的partition
爲1(或者partition不足導致的)
,只往一臺機器上寫數據,造成kafka集羣空間使用不均。
下面主要使用kafka-topics.sh
和kafka-reassign-partitions.sh
來解決問題。
推薦使用kafka manager來管理kafka集羣。
而kafka的partition離不開
Controller 的監聽,先介紹一下Controlle。
1 Kafka Controller 作用
Controller 在初始化時,會利用 ZK 的 watch 機制註冊很多不同類型的監聽器,當監聽的事件被觸發時,Controller 就會觸發相應的操作。
Controller 在初始化時,會註冊多種類型的監聽器,主要有以下6種:
- 監聽
/admin/reassign_partitions
節點,用於分區副本遷移的監聽; - 監聽
/isr_change_notification
節點,用於 Partition Isr 變動的監聽,; - 監聽
/admin/preferred_replica_election
節點,用於需要進行 Partition 最優 leader 選舉的監聽; - 監聽
/brokers/topics
節點,用於 Topic 新建的監聽; - 監聽
/brokers/topics/TOPIC_NAME
節點,用於 Topic Partition 擴容的監聽; - 監聽
/admin/delete_topics
節點,用於 Topic 刪除的監聽; - 監聽
/brokers/ids
節點,用於 Broker 上下線的監聽。
本文主要講解第一部分,也就是 Controller 對 Partition 副本遷移的處理。
2 操作
2.1 修改topic的partitions
./bin/kafka-topics.sh --zookeeper vlnx111122:2181 --alter --topic test --partitions 6
此命令執行完之後即可再kafka集羣其他機器中找到此topic的目錄
2.2 擴容、刪除機器
只要配置zookeeper.connect爲要加入的集羣,再啓動Kafka進程,就可以讓新的機器加入到Kafka集羣。但是新的機器只針對新的Topic纔會起作用,在之前就已經存在的Topic的分區,不會自動的分配到新增加的物理機中。
爲了使新增加的機器可以分擔系統壓力,必須進行消息數據遷移。Kafka提供了kafka-reassign-partitions.sh
進行數據遷移。
這個腳本提供3個命令:
--generate
: 根據給予的Topic列表和Broker列表生成遷移計劃。generate並不會真正進行消息遷移,而是將消息遷移計劃計算出來,供execute命令使用。--execute
: 根據給予的消息遷移計劃進行遷移。--verify
: 檢查消息是否已經遷移完成。
2.3 Partition 副本遷移整體流程
Partition 的副本遷移實際上就是將分區的副本重新分配到不同的代理節點上,如果 zk 中新副本的集合與 Partition 原來的副本集合相同,那麼這個副本就不需要重新分配了。
Partition 的副本遷移是通過監聽 zk 的 /admin/reassign_partitions
節點觸發的,Kafka 也向用戶提供相應的腳本工具進行副本遷移,副本遷移的腳本使用方法如下所示:
./bin/kafka-reassign-partitions.sh --zookeeper XXX --reassignment-json-file XXX.json --execute
其中 XXX.json 爲要進行 Partition 副本遷移的 json 文件,json 文件的格式如下所示:
{
"version":1,
"partitions":[
{
"topic":"__consumer_offsets",
"partition":19,
"replicas":[
3,
9,
2
]
},
{
"topic":"__consumer_offsets",
"partition":26,
"replicas":[
2,
6,
4
]
},
{
"topic":"__consumer_offsets",
"partition":27,
"replicas":[
5,
3,
8
]
}
]
}
這個 json 文件的意思是將 Topic __consumer_offsets
Partition 19 的副本遷移到 {3, 2, 9} 上,Partition 26 的副本遷移到 {6, 2, 4} 上,Partition 27 的副本遷移到 {5, 3, 8} 上。
3. 示例
3.1 實例1
3.1.1 配置Kafka的server.properties
包括配置broker id等
3.1.2 啓動新broker
~/kafka/bin/kafka-server-start.sh -daemon ~/kafka/config/server.properties
停止命令:~/kafka/bin/kafka-server-stop.sh
3.1.3 手動生成一個json文件topic.json
topic爲test
目前在broker id爲1,2,3的機器上,現又添加了兩臺機器,broker id爲4,5,現在想要將壓力平均分散到這5臺機器上。
手動生成一個json文件topic.json
{
"topics": [
{"topic": "test"}
],
"version": 1
}
3.1.4 調用--generate
生成遷移計劃
,將test
擴充到所有機器上
./bin/kafka-reassign-partitions.sh --zookeeper vlnx111122:2181 --topics-to-move-json-file topic.json --broker-list "1,2,3,4,5" --generate
生成類似於下方的結果
Current partition replica assignment
{"version":1,
"partitions":[....]
}
Proposed partition reassignment configuration
{"version":1,
"partitions":[.....]
}
Current partition replica assignment
表示當前的消息存儲狀況。
Proposed partition reassignment configuration
表示遷移後的消息存儲狀況。
那麼我們就用下部分的json進行遷移。另外,也可以自己構造個類似的json文件,同樣可以進行遷移。
將遷移後的json存入一個文件reassignment.json
,供--execute
命令使用。
3.1.5 執行--execute
進行擴容。
./bin/kafka-reassign-partitions.sh --zookeeper vlnx111122:2181 --reassignment-json-file reassignment.json --execute
Current partition replica assignment
...
Save this to use as the --reassignment-json-file option during rollback
...
3.1.6 使用--verify
查看進度
./bin/kafka-reassign-partitions.sh --zookeeper vlnx111122:2181 --reassignment-json-file reassignment.json --verify
3.2 實例2
3.2.1 修改topic partitions數量
- [root@bigserver2 kafka]# ./bin/kafka-topics.sh --zookeeper bigserver1:2181,bigserver2:2181,testing:2181 --alter --topic track_pc --partitions 3
- WARNING: If partitions are increased for a topic that has a key, the partition logic or ordering of the messages will be affected
- Adding partitions succeeded!
- [root@bigserver2 kafka]# bin/kafka-topics.sh --describe --zookeeper bigserver1:2181,bigserver2:2181,testing:2181 --topic track_pc
- Topic:track_pc PartitionCount:3 ReplicationFactor:1 Configs:
- Topic: track_pc Partition: 0 Leader: 1 Replicas: 1 Isr: 1
- Topic: track_pc Partition: 1 Leader: 2 Replicas: 2 Isr: 2
- Topic: track_pc Partition: 2 Leader: 0 Replicas: 0 Isr: 0
分區由原來一個變成了三個,並且集羣裏面的所有kafka,data目錄都會產生相應的文件夾
3.2.2 生成均衡配置文件
- [root@bigserver2 kafka]# cat track_pc.json //創建配置文件
- {
- "topics": [
- {"topic": "track_pc"}
- ],
- "version": 1
- }
- [root@bigserver2 kafka]# bin/kafka-reassign-partitions.sh --zookeeper bigserver1:2181,bigserver2:2181,testing:2181 --topics-to-move-json-file track_pc.json --broker-list "0,1,2" --generate
- Current partition replica assignment
- {"version":1,"partitions":[{"topic":"track_pc","partition":0,"replicas":[1],"log_dirs":["any"]},{"topic":"track_pc","partition":2,"replicas":[0],"log_dirs":["any"]},{"topic":"track_pc","partition":1,"replicas":[2],"log_dirs":["any"]}]}
- Proposed partition reassignment configuration
- {"version":1,"partitions":[{"topic":"track_pc","partition":0,"replicas":[0],"log_dirs":["any"]},{"topic":"track_pc","partition":2,"replicas":[2],"log_dirs":["any"]},{"topic":"track_pc","partition":1,"replicas":[1],"log_dirs":["any"]}]}
注意:0,1,2是kafka配置文件中的broker.id,在這裏只是生成配置文件,並沒有真正均衡
3.2.3 均衡partitions
將2中,生成的json,copy到一個json文件中,執行以下命令
- # bin/kafka-reassign-partitions.sh --zookeeper bigserver1:2181,bigserver2:2181,testing:2181 --reassignment-json-file exec.json --execute
- Current partition replica assignment
- {"version":1,"partitions":[{"topic":"track_pc","partition":0,"replicas":[1],"log_dirs":["any"]},{"topic":"track_pc","partition":2,"replicas":[0],"log_dirs":["any"]},{"topic":"track_pc","partition":1,"replicas":[2],"log_dirs":["any"]}]}
- Save this to use as the --reassignment-json-file option during rollback
- Successfully started reassignment of partitions.
- [root@bigserver2 kafka]# bin/kafka-reassign-partitions.sh --zookeeper bigserver1:2181,bigserver2:2181,testing:2181 --reassignment-json-file exec.json --verify
- Status of partition reassignment:
- Reassignment of partition track_pc-0 is still in progress
- Reassignment of partition track_pc-2 is still in progress
- Reassignment of partition track_pc-1 is still in progress
- [root@bigserver2 kafka]# bin/kafka-reassign-partitions.sh --zookeeper bigserver1:2181,bigserver2:2181,testing:2181 --reassignment-json-file exec.json --verify
- Status of partition reassignment:
- Reassignment of partition track_pc-0 completed successfully
- Reassignment of partition track_pc-2 completed successfully
- Reassignment of partition track_pc-1 completed successfully
注意:到這裏均衡已結束,但是對已有的數據,並不能起到均衡作用。
4. broker 處理遷移的思路總結
broker會watch "/admin/reassign_partitions"節點。當發現有遷移任務的時候,會將partiton的AR進行擴展,例如原先partiton的AR是[1, 2], 現在要遷移到[2, 3],那麼partiton會先將AR擴展到[1, 2, 3],並監控ISR的變化。
當replica-2和replica-3都跟上後,即在ISR中的時候,表明新的repica-3已經和leader數據同步了。這個時候就可以將replica-1剔除了,最後得到遷移結果是[2, 3]。即遷移是一個先增加再減少的過程。
5. 可能遇到的問題
5.1 報錯
Assigned replicas (0,1) don't match the list of replicas for reassignment (1,0) for partition [testTopic,0] Reassignment of partition [testTopic,0] failed
在2.1.2中已經說明了,該錯誤是由於"/admin/reassign_partitions"節點已經被刪除了,但是AR和目標遷移列表不相同報的錯,一般需要看下controller的日誌,看下controller在遷移過程中是不是拋出了異常。
5.2 遷移一直在進行中,不能完成
遷移需要等目標遷移列表中的replic都跟上了leader才能完成,目前遷移列表一直跟不上,那麼就不會完成。可以看下zk中“/brokers/topics/{topic}/partitions/{partiton}/state”,注意下目標遷移列表是不是在isr中,如果不在說明要遷移的replic還沒有完成從leader拉取數據。具體爲甚麼沒有拉取成功,可能是數據量比較大,拉取需要一定的時間;也可能是其他原因比如集羣宕機了等,需要具體分析下
6. 相關命令
./bin/kafka-console-producer.sh --broker-list vlnx111111:9092 --topic test
./bin/kafka-console-consumer.sh --zookeeper vlnx111122:2181 --topic test --from-beginning
./bin/kafka-topics.sh --zookeeper vlnx111122:2181 --list
./bin/kafka-topics.sh --zookeeper vlnx111122:2181 --create --replication-factor 2 --partition 6 --topic test
./bin/kafka-topics.sh --zookeeper vlnx111122:2181 --delete --topic test
./bin/kafka-topics.sh --zookeeper vlnx111122:2181 --describe --topic test
7 參考:
https://cwiki.apache.org/confluence/display/KAFKA/Replication+tools
https://wzktravel.github.io/2015/12/31/kafka-reassign/
http://blog.51yip.com/hadoop/2131.html
https://www.cnblogs.com/set-cookie/p/9614241.html
https://matt33.com/2018/06/16/partition-reassignment/