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