Kafka高可用性原理
分散式系統中,任何機器都可能面臨未知的宕機風險,所以很高可用涉及是一個不可避免的話題。但是高可用帶來的代價就是一致性問題,這又是一個很大很有趣的話題了。今天我們僅來談談kafka的高可用設計。
高可用設計
實現高可用性的方式一般都是進行replication,對於kafka,如果沒有提供High Availablity機制,一旦一個或多個Broker宕機,則宕機期間其上所有Partition都無法繼續提供服務。若該Broker永遠不能再恢復,那麼所有的資料也就將丟失,這是不可容忍的。所以kafka高可用性的設計也是進行Replication。
Replica如何分佈
為了儘量做好負載均衡和容錯能力,需要將同一個Partition的Replica儘量分散到不同的機器。如果所有的Replica都在同一個Broker上,那一旦該Broker宕機,該Partition的所有Replica都無法工作,那麼這些Replica也就失去的意義。
Replica如何同步
當沒有Replica的時候,producer向broker寫入訊息非常簡單,當有很多Replica的時候是如何處理的呢?
一般來說,對於這種情況有兩個處理方法
- 同步複製,當producer向所有的Replica寫入成功訊息後才返回。一致性得到保障,但是延遲太高,吞吐率降低。
- 非同步複製,所有的Replica選取一個一個leader,producer向leader寫入成功即返回,leader負責將訊息同步給其他的所有Replica。但是訊息同步一致性得不到保證,但是保證了快速的響應。
而kafka選取了一個折中的方式:ISR(in-sync replicas)。producer每次傳送訊息,將訊息傳送給leader,leader將訊息同步給他“信任”的“小弟們”就算成功,巧妙的均衡了確保資料不丟失以及吞吐率。具體的,
- 在所有的Replica中,leader會維護一個與其基本保持同步的Replica列表,該列表稱為ISR(in-sync Replica),每個Partition都會有一個ISR,而且是由leader動態維護。
- 如果一個replica落後leader太多,leader會將其剔除。如果另外的replica跟上腳步,leader會將其加入。
- 同步:leader向ISR中的所有replica同步訊息,當收到所有ISR中replica的ack之後,leader才commit。
非同步:收到同步訊息的ISR中的replica,非同步將訊息同步給ISR集合外的replica。
如何Leader Election
瞭解了Kafka如何做Replication,隨之而來的疑問便是如何選取leader?
leader選舉可謂是一個經典問題,立馬想到了paxos,raft、Zab等演算法,然而kafka採用的方法相比就簡單很多:
Kafka的Leader選舉是通過在zookeeper上建立/controller臨時節點來實現leader選舉,並在該節點中寫入當前broker的元資訊。一個節點只能被一個客戶端建立成功,建立成功的broker即為leader,即先到先得原則。
當leader和zookeeper失去連線時,臨時節點會刪除,而其他broker會監聽該節點的變化,當節點刪除時,其他broker會收到事件通知,重新發起leader選舉。
如果所有的replica都不工作了?
兩種方式
- 等待ISR中任一個Replica恢復,並選取他為leader
- 等待時間較長,降低了可用性
- 若ISR中的所有Replica都無法恢復或者資料丟失,則改partition將永不可用
- 選擇第一個回覆的Replica為新的leader,無論他是否在ISR中
- 所選leader可能並未包含已被之前leader commit的訊息,因此會造成資料丟失
- 可用性較高