Kafka:你必須要知道集群內(nèi)部工作原理的一些事!
前言
上篇文章講到了消息在 Partition 上的存儲(chǔ)形式,本來(lái)準(zhǔn)備接著來(lái)聊聊生產(chǎn)中的一些使用方式,想了想還有些很重要的工作組件原理沒有講清楚,比如一個(gè) Topic 由 N 個(gè) Partition 組成,那么這些 Partition 是如何均勻的分布在不同的 Broker 上?再比如當(dāng)一個(gè) Broker 宕機(jī)后,其上負(fù)責(zé)讀寫請(qǐng)求的主 Partition 無(wú)法正常訪問,如何讓從 Partition 轉(zhuǎn)變成主 Partition 來(lái)繼續(xù)提供正常的讀寫服務(wù)?想要解決這些問題,就必須先要了解一下 Kafka 集群內(nèi)部的管理機(jī)制,其中一個(gè)非常重要的控制器就是 KafkaController。本文我們就來(lái)講講 KafkaController 是如何來(lái)解決上面提到的那些問題的。
文章概覽
-
KafkaController 是什么及其選舉策略。 -
KafkaController 監(jiān)控 ZK 的目錄分布。 -
Partition 分布算法。 -
Partition 的狀態(tài)轉(zhuǎn)移。 -
Kafka 集群的負(fù)載均衡處理流程解析。
KafkaController 是什么及其選舉策略
Kafka 集群由多臺(tái) Broker 構(gòu)成,每臺(tái) Broker 都有一個(gè) KafkaController 用于管理當(dāng)前的 Broker。試想一下,如果一個(gè)集群沒有一個(gè)“領(lǐng)導(dǎo)者”,那么誰(shuí)去和“外界”(比如 ZK)溝通呢?誰(shuí)去協(xié)調(diào) Partition 應(yīng)該如何分布在集群中的不同 Broker 上呢?誰(shuí)去處理 Broker 宕機(jī)后,在其 Broker 上的主 Partition 無(wú)法正常提供讀寫服務(wù)后,將對(duì)應(yīng)的從 Partition 轉(zhuǎn)變成主 Partition 繼續(xù)正常對(duì)外提供服務(wù)呢?那么由哪個(gè) Broker 的 KafkaController 來(lái)?yè)?dān)當(dāng)“領(lǐng)導(dǎo)者”這個(gè)角色呢?
Kafka 的設(shè)計(jì)者很聰明,Zookeeper 既然是分布式應(yīng)用協(xié)調(diào)服務(wù),那么干脆就讓它來(lái)幫 Kafka 集群選舉一個(gè)“領(lǐng)導(dǎo)者”出來(lái),這個(gè)“領(lǐng)導(dǎo)者”對(duì)應(yīng)的 KafkaController 稱為 Leader,其他的 KafkaController 被稱為 Follower,在同一時(shí)刻,一個(gè) Kafka 集群只能有一個(gè) Leader 和 N 個(gè) Follower。
Zookeeper 是怎么實(shí)現(xiàn) KafkaController 的選主工作呢?
稍微熟悉 Zookeeper 的小伙伴應(yīng)該都比較清楚,Zookeeper 是通過監(jiān)控目錄(zNode)的變化,從而做出一些相應(yīng)的動(dòng)作。
Zookeeper 的目錄分為四種,第一種是永久的,被稱作為 Persistent
;
第二種是順序且永久的,被稱作為 Persistent_Sequential
;
第三種是臨時(shí)的,被稱為 Ephemeral
;
第四種是順序且臨時(shí)的,被稱作為 Ephemeral_Sequential
。
KafkaController 正是利用了臨時(shí)的這一特性來(lái)完成選主的,在 Broker 啟動(dòng)時(shí),每個(gè) Broker 的 KafkaController 都會(huì)向 ZK 的 /controller
目錄寫入 BrokerId,誰(shuí)先寫入誰(shuí)就是 Leader,剩余的 KafkaController 是 Follower,當(dāng) Leader 在周期內(nèi)沒有向 ZK 發(fā)送報(bào)告的話,則認(rèn)為 Leader 掛了,此時(shí) ZK 刪除臨時(shí)的 /controller
目錄,Kafka 集群中的其他 KafkaController 開始新的一輪爭(zhēng)主操作,流程和上面一樣。下面是選 Leader 的流程圖。
從上圖可以看出,第一次,Broker1 成功搶先在 Zookeeper 的 /controller 目錄上寫入信息,所以 Broker1 的 KafkaController 為 Leader,其他兩個(gè)為 Follower。第二次,Broker1 宕機(jī)或者下線,此時(shí) Broker2 和 Broker3 檢測(cè)到,于是開始新一輪的爭(zhēng)搶將信息寫入 Zookeeper,從圖中可以看出,Broker2 爭(zhēng)到了 Leader,所以 Broker3 是 Follower 狀態(tài)。
正常情況下,上面這個(gè)流程沒有問題,但是如果在 Broker1 離線的情況下,Zookeeper 準(zhǔn)備刪除 /controller 的臨時(shí) node 時(shí),系統(tǒng) hang 住沒辦法刪除,改怎么辦呢?這里留個(gè)小疑問供大家思考。后面會(huì)用一篇文章專門來(lái)解答 Kafka 相關(guān)的問題(包括面試題哦,敬請(qǐng)期待)。
KafkaController 監(jiān)控的 ZK 目錄分布
KafkaController 在初始化的時(shí)候,會(huì)針對(duì)不同的 zNode 注冊(cè)各種各樣的監(jiān)聽器,以便處理不同的用戶請(qǐng)求或者系統(tǒng)內(nèi)部變化請(qǐng)求。監(jiān)控 ZK 的目錄大概可以分為兩部分,分別是 /admin
目錄和 /brokers
目錄。各目錄及其對(duì)應(yīng)的功能如下表所示,需要的朋友自提。
父目錄 | 子目錄 | 監(jiān)控對(duì)象 | 作用 |
---|---|---|---|
/admin | /reassign_partitions | PartitionReassignedListener | 監(jiān)聽重新分配 Topic 的 Partition 的請(qǐng)求 |
/admin | /preferred_replica_election | PreferredReplicaElectionListener | 監(jiān)聽重新選舉 Topic 分區(qū)副本的請(qǐng)求(因?yàn)槊總€(gè) Partition 也有主從的區(qū)別) |
/admin | /delete_topics | DeleteTopicListener | 監(jiān)聽刪除 Topic 的請(qǐng)求 |
/brokers | /topics | TopicChangeListener | 監(jiān)聽創(chuàng)建 Topic 的請(qǐng)求 |
/brokers | /topics/Topic-P0 | AddPartitionsListener | 監(jiān)聽增加 Partition 的請(qǐng)求 |
/brokers | /topics/Topic-P0/0/state | ReassignedPartitionsLsrChangeListner | 監(jiān)聽 Topic 的 ISR(正在同步的 Partition)列表的變化 |
/brokers | /ids | BrokerChangeListener | 監(jiān)聽 Broker 上下線引起的 Topic 元數(shù)據(jù)信息的變化 |
Partition 分布算法
圖解:假設(shè)集群有 3 個(gè) Broker,Partition 因子為 2。
-
隨機(jī)選取 Broker 集群中的一個(gè) Broker 節(jié)點(diǎn),然后以輪詢的方式將主 Partition 均勻的分布到不同的 Broker 上。 -
主 Partition 分布完成后,將從 Partition 按照 AR 組內(nèi)順序以輪詢的方式將 Partition 均勻的分布到不同的 Broker 上。
Partition 的狀態(tài)轉(zhuǎn)移
用戶針對(duì)特定的 Topic 創(chuàng)建了相應(yīng)的 Partition ,但是這些 Partition 不一定時(shí)刻都能夠正常工作,所有 Partition 在同一時(shí)刻會(huì)對(duì)應(yīng) 4 個(gè)狀態(tài)中的某一個(gè);其整個(gè)生命周期會(huì)經(jīng)歷如下狀態(tài)的轉(zhuǎn)移,分別是 NonExistentPartition、NewPartition、OnlinePartition、OfflinePartition,其對(duì)應(yīng)的狀態(tài)轉(zhuǎn)移情況如下圖所示。
從上圖可以看出,Partition 的狀態(tài)會(huì)由前置狀態(tài)才能夠轉(zhuǎn)移到目標(biāo)狀態(tài)的,而不是胡亂轉(zhuǎn)移狀態(tài)的。
NonExistentPartition:
代表沒有創(chuàng)建 Partition 時(shí)的狀態(tài),也有可能是離線的 Partition 被刪除后的狀態(tài)。
NewPartition:
當(dāng) Partition 被創(chuàng)建時(shí),此時(shí)只有 AR(Assigned Replica),還沒有 ISR(In-Synic Replica),此時(shí)還不能接受數(shù)據(jù)的寫入和讀取。
OnlinePartition:
由 NewPartition 狀態(tài)轉(zhuǎn)移為 OnlinePartition 狀態(tài),此時(shí) Partition 的 Leader 已經(jīng)被選舉出來(lái)了,并且也有對(duì)應(yīng)的 ISR 列表等。此時(shí)已經(jīng)可以對(duì)外提供讀寫請(qǐng)求了。
OfflinePartition:
當(dāng) Partition 對(duì)應(yīng)的 Broker 宕機(jī)或者網(wǎng)絡(luò)異常等問題,由 OnlinePartition 轉(zhuǎn)移到 OfflinePartition,此時(shí)的 Partition 已經(jīng)不能在對(duì)外提供讀寫服務(wù)。當(dāng) Partition 被徹底刪除后狀態(tài)就轉(zhuǎn)移成 NonExistentPartition,當(dāng)網(wǎng)絡(luò)恢復(fù)或者 Broker 恢復(fù)后,其狀態(tài)又可以轉(zhuǎn)移到 OnlinePartition,從而繼續(xù)對(duì)外提供讀寫服務(wù)。
Kafka 集群的負(fù)載均衡處理流程解析
前面的文章講到過,Partition 有 Leader Replica 和 Preferred Replica 兩種角色,Leader Replica 負(fù)責(zé)對(duì)外提供讀寫服務(wù) Preferred Replica 負(fù)責(zé)同步 Leader Replica 上的數(shù)據(jù)?,F(xiàn)在集群中假設(shè)有 3 個(gè) Broker,3 個(gè) Partition,每個(gè) Partition 有 3 個(gè) Replica,當(dāng)集群運(yùn)行一段時(shí)候后,集群中某些 Broker 宕機(jī),Leader Replica 進(jìn)行轉(zhuǎn)移,其過程如下圖所示。
從上圖可以看出,集群運(yùn)行一段時(shí)間后,Broker1 掛掉了,在其上運(yùn)行的 Partition0 對(duì)應(yīng)的 Leader Replica 轉(zhuǎn)移到了 Broker2 上。假設(shè)一段時(shí)間后 Broker3 也掛了,則 Broker3 上的 Partition3 對(duì)應(yīng)的 Leader Replica 也轉(zhuǎn)移到了 Broker2 上,集群中只有 Broker2 上的 Partition 在對(duì)外提供讀寫服務(wù),從而造成 Broker2 上的服務(wù)壓力比較大,之后 Broker1 和 Broker3 恢復(fù)后,其上只有 Preferred Replica 做備份操作。
針對(duì)以上這種隨著時(shí)間的推移,集群不在像剛開始時(shí)那樣平衡,需要通過后臺(tái)線程將 Leader Replica 重新分配到不同 Broker 上,從而使得讀寫服務(wù)盡量均勻的分布在不同的節(jié)點(diǎn)上。
重平衡操作是由 partition-rebalance-thread 后臺(tái)線程操作的,由于其優(yōu)先級(jí)很低,所以只會(huì)在集群空閑的時(shí)候才會(huì)執(zhí)行。集群的不平衡的評(píng)判標(biāo)準(zhǔn)是由leader.imbalance.per.broker.percentage
配置決定的,當(dāng)集群的不平衡度達(dá)到 10%(默認(rèn))時(shí),會(huì)觸發(fā)后臺(tái)線程啟動(dòng)重平衡操作,其具體執(zhí)行步驟如下:
-
對(duì) Partition 的 AR 列表根據(jù) Preferred Replica 進(jìn)行分組操作。 -
遍歷 Broker,對(duì)其上的 Partition 進(jìn)行處理。 -
統(tǒng)計(jì) Broker 上的 Leader Replica 和 Preferred Replica 不相等的 Partition 個(gè)數(shù)。 -
統(tǒng)計(jì) Broker 上的 Partition 個(gè)數(shù)。 -
Partition 個(gè)數(shù) / 不相等的 Partition 個(gè)數(shù),如果大于 10%,則觸發(fā)重平衡操作;反之,則不做任何處理。
總結(jié)
本文主要介紹了 Kafka 集群服務(wù)內(nèi)部的一些工作機(jī)制,相信小伙伴們掌握了這部分內(nèi)容后,對(duì) Broker 服務(wù)端的工作流程有了進(jìn)一步的理解,從而更好的把控整體集群服務(wù)。下篇文章我們來(lái)正式介紹一下Kafka 常用的命令行操作,敬請(qǐng)期待。
特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:
長(zhǎng)按訂閱更多精彩▼
如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!