這是一篇關(guān)于 Kafka 集群基本的組織和管理方式的原理總結(jié)悲关,我盡量讓它不枯燥。
內(nèi)容提要:
- 背景知識
- 名詞介紹
- 集群的基本組織方式
- broker 的啟動
- broker 的監(jiān)聽
- controller 的選舉和作用
- controller 的選舉
- controller 的重新選舉
- controller 管理 broker 的離開和加入
- leader 和 follower 的關(guān)系
請您用絕對的理智和清醒的頭腦去壓制住心里的愛和難過娄柳,站在未來的高點去否定當下沒意義的事寓辱。
1. 背景知識
本文需要了解 Zookeeper 的基礎(chǔ)知識,可以參考這篇:https://segmentfault.com/a/1190000016349824西土。
本文涉及到 ZooKeeper的點包括:
- ZooKeeper 一種常用的分布式協(xié)調(diào)服務(wù)讶舰,Kafka 用到了它的數(shù)據(jù)發(fā)布和訂閱、命名服務(wù)需了、分布式協(xié)調(diào)/通知跳昼、集群管理、Master 選舉等功能肋乍。
- ZooKeeper 在內(nèi)存中用一棵樹存儲數(shù)據(jù)鹅颊,樹中的每個節(jié)點用于存儲數(shù)據(jù),數(shù)據(jù)節(jié)點分為永久的和臨時的兩種墓造,只要創(chuàng)建臨時節(jié)點的客戶端下線了臨時節(jié)點就會被刪除堪伍,永久節(jié)點不會。
- 客戶端可以監(jiān)聽指定的數(shù)據(jù)節(jié)點觅闽,當特定的事件發(fā)生時帝雇,ZooKeeper 會通知客戶端,比如監(jiān)聽節(jié)點的刪除蛉拙、創(chuàng)建或修改尸闸。
- ZooKeeper 的中文意思是“動物管理員”,因為很多用到 ZooKeeper 的項目名或者 logo 都是動物孕锄,比如 Pig吮廉、Hadoop 等。
由于是一遍學習理論一遍驗證它畸肆,因此最好有可以訪問的 Kafka 集群或者單機的 Kafka宦芦,單機 Kafka 的安裝使用可以參考 [Kafka 101-1] Kafka安裝使用。
2. 名詞介紹
先羅列一下將會出現(xiàn)的新名詞轴脐,認個眼熟(有些名詞用中文說很奇怪调卑,所以會用英文):
英文 | 中文 | 解釋 |
---|---|---|
cluster | 集群 | 所有 Kafka broker 組成的集群 |
controller | 控制者 | Kafka broker 中比較特殊的一個,相當于其他主從結(jié)構(gòu)系統(tǒng)中的 master |
replication | 副本 | 同一分區(qū)的數(shù)據(jù)會在不同的 broker 上存儲多份豁辉,每一份都稱為一個副本 |
leader | 領(lǐng)導者 | 同一分區(qū)的副本中 |
follower | 跟隨者 | 持有分區(qū)副本的 broker令野,不是領(lǐng)導者的就是跟隨者,唯一的任務(wù)就是從領(lǐng)導者同步最新的消息徽级,相當于備用領(lǐng)導者 |
3. 集群的基本組織方式
broker 的啟動
當每個 broker 啟動時气破,會在 ZooKeeper 中的 /brokers/ids
路徑下創(chuàng)建一個節(jié)點來注冊自己,節(jié)點 ID 為配置文件中的 broker.id
參數(shù)餐抢,不同節(jié)點不可以指定相同的 ID现使,后注冊的 broker 會報 NodeExists
的錯低匙。
如果不指定
broker.id
或者指定成 -1,節(jié)點 ID 會從reserved.broker.max.id
這個參數(shù)加 1 的值開始碳锈,這個參數(shù)默認值是 1000顽冶,所以經(jīng)常可以看見 1001售碳、1002 的 broker ID强重。
用 ZooKeeper 的命令行工具來查看一下數(shù)據(jù)節(jié)點的情況(不同安裝方式 ZooKeeper 的命令會有所不同):
我用 ls /
查看了 ZooKeeper 根路徑下的節(jié)點,可以看到 brokers
贸人、controller
间景、consumers
等節(jié)點,ZooKeeper 的命令很簡單艺智,可以用 help
來查看所有的命令倘要,不過我一般只用 ls
和 get
兩個。
來看下 /brokers/ids
路徑下的內(nèi)容:
可以看到下面注冊了兩個節(jié)點十拣,1001 是我額外又啟動的一個 broker(修改配置文件封拧,log.dirs
和 listeners
參數(shù)改成不一樣的即可),我把 broker.id
設(shè)置成了-1夭问,注冊出來就是 1001泽西。用 get /brokers/ids/0
命令來查看 broker 注冊的信息,里面包含了 broker 的 IP 和端口缰趋、注冊時間尝苇、版本以及其它屬性,這種樹形結(jié)構(gòu)和文件系統(tǒng)結(jié)構(gòu)非常類似埠胖。
broker 的監(jiān)聽
每個 broker 除了注冊自身之外,還會監(jiān)聽 /brokers/ids
這個節(jié)點淳玩,當這個節(jié)點下增加或刪除子幾點時直撤,ZooKeeper 會通知監(jiān)聽了的 broker。每個 broker 創(chuàng)建的節(jié)點都是臨時節(jié)點蜕着,如果 broker 下線谋竖,/brokers/ids
下對應(yīng)的節(jié)點就會被刪除。
注意:broker 下線承匣,只會刪除
/brokers/ids
下的節(jié)點蓖乘,其它的節(jié)點中可能還包含這個 broker 的 ID,比如/brokers/toics
下的節(jié)點會記錄每個分區(qū)的副本存儲在哪些 broker 上韧骗,這些節(jié)點不會刪除這個 broker 的 ID嘉抒,因為這個 broker 還有可能恢復,如果恢復不了袍暴,可以用相同的 ID 啟動一個新的 broker些侍,新的 broker 會代替原來 broker 的位置隶症,開始同步數(shù)據(jù)。
4. controller 的作用
controller 除了是一個普通的 broker 之外岗宣,還是集群的總扛把子蚂会,它負責副本 leader 的選舉、topic 的創(chuàng)建和刪除耗式、副本的遷移胁住、副本數(shù)的增加、broker 上下線的管理等等刊咳,這一小節(jié)主要關(guān)注副本 leader 的選舉這一個功能彪见。
controller 的選舉
和很多主從架構(gòu)的分布式系統(tǒng)不同(比如HDFS 的 namenode 和 datanode 是指定的),Controller 的選舉靠“命”芦缰。
選舉過程如下:每個 broker 啟動的時候其實都想成為 controller企巢,成為 controller 的方法就是在 ZooKeeper 中創(chuàng)建 /controller
臨時節(jié)點節(jié)點并注冊自己的信息,先注冊上的 broker 就是 controller让蕾,后來的發(fā)現(xiàn)已經(jīng)有這個節(jié)點就知道已經(jīng)有人搶先了浪规,就放棄了,但是它們會監(jiān)聽這個節(jié)點的狀態(tài)探孝,伺機而動笋婿。
用 get /controller
命令看下這個節(jié)點的內(nèi)容:
可以看到,ID 為 0 的 broker 目前是 controller顿颅。
controller的重新選舉
當 controller 下線時缸濒,因為無法和 ZooKeeper 保持心跳,/controller
臨時節(jié)點會被刪除粱腻,每個 broker 發(fā)現(xiàn)這一點之后庇配,就開始新一輪的選舉(其實就是搶)。選舉出新 controller 的同時绍些,/controller_epoch
中的值也會加 1捞慌,這個節(jié)點記錄 controller 的代數(shù),broker 也會監(jiān)聽這個節(jié)點柬批,并且知道當前 controller 的代數(shù)啸澡,舊的 controller 的指令即使繼續(xù)發(fā)送指定給它們,指令也會被忽略氮帐。
重新選舉的過程過程也可以手動觸發(fā)嗅虏,我們在 ZooKeeper 里用 rmr /controller
命令刪掉這個節(jié)點,然后再查看這個節(jié)點:
果然上沐,controller 換人了皮服。
controller 管理 broker 的離開和加入
當有 broker 下線時,由于這個 broker 可能是多個分區(qū)的 leader,所以 controller 需要給這些分區(qū)重新選舉一個新的 leader冰更,說是選舉产徊,其實就是直接指定每個分區(qū)副本列表里的下一個 broker,舉個例子:
iamabug-5 這個 topic 創(chuàng)建時有三個分區(qū)蜀细,每個分區(qū)有三個副本舟铜,分區(qū) 0 的 leader 最好是 1004,為什么說是最好呢奠衔,因為 leader 需要處理所有客戶端的請求谆刨,任務(wù)比較重,Kafka 有一套負載均衡機制來確定每個分區(qū)的 leader 應(yīng)該在哪臺 broker 上归斤,這個 broker 叫做 preferred_leader
痊夭,且跟在 1004 后面的 broker ID 是 1002,在沒有 broker 下線的時候脏里,看下分區(qū) 0 的 leader:
這樣的狀態(tài)是正常的她我,注意 leader_epoch
值為 6,表示當前 leader 的代數(shù)迫横,現(xiàn)在我把 1004 這臺 broker 關(guān)掉番舆,會發(fā)生什么變化:
leader 變成 1002 了,并且 leader_epoch
變成了 7矾踱,這個過程中恨狈,controller 會向這個分區(qū)的所有副本,也就是 1001 和 1002 發(fā)送 leader 變更的通知呛讲,然后 1002 就成為 leader 并開始處理客戶端的生產(chǎn)和消費請求禾怠。
假如 1004 這臺 broker 又重新上線呢?
可以看到贝搁,1004 會重新變成這個分區(qū)的 leader吗氏,并且 leader_epoch
又加了 1,因為它是 preferred leader雷逆,但這個過程并不是立馬發(fā)生的牲证,broker 有一個參數(shù)叫做 leader.imbalance.check.interval.seconds
,默認值為 300关面,也就是每 5 分鐘會檢測一次每個分區(qū)的 leader 是不是 preferred leader, 如果不是的話十厢,會主動更換 leader等太。
因為實驗了聽多次,我偷偷啟動了很多次 broker 進程蛮放,所以 broker 的 ID 前后有點不一樣缩抡。
leader 和 follower 的關(guān)系
我們已經(jīng)知道,在每個分區(qū)的多個副本中包颁,有一個是 leader瞻想,其它是 follower压真,follower 就干一件事,從 leader 同步數(shù)據(jù)蘑险,然后等著 leader 掛掉滴肿,自己有機會成為 leader。
leader干兩件事佃迄,一是服務(wù)用戶發(fā)來的生產(chǎn)和消費請求泼差,二是監(jiān)控 follower 同步數(shù)據(jù)的進度,只有一直和 leader 保持同步的 follower 才有機會成為下一個 leader呵俏,那么保持同步的標準是什么呢堆缘?標準就是,如果一個 follower 超過 10 秒沒有向 leader 請求數(shù)據(jù)或者請求數(shù)據(jù)了普碎,但是沒有在 10 秒內(nèi)跟上 leader 的最新消息吼肥,那么這個 follower 就是不同步的,當然這里的 10 秒是個可配置的參數(shù)麻车,叫做 replica.lag.time.max.ms
缀皱。
對于能夠和 leader 保持同步的 follower,有個專門的名詞就做 ISR绪氛,是 in-sync replicas 的縮寫唆鸡,其實在上面的截圖里也可以看到每個 partition 也會維護哪些 follower 是在 ISR 里的。
本文內(nèi)容有點多枣察,時間有點緊争占,可能錯誤疏漏較多,歡迎指出序目,并請見諒臂痕!
歡迎交流討論,吐槽建議猿涨,分享收藏握童。
勤學似春起之苗,不見其增叛赚,日有所長
輟學如磨刀之石澡绩,不見其損,日有所虧
關(guān)注【大數(shù)據(jù)學徒】俺附,用技術(shù)干貨助你日有所長