《英靈神殿》一週年內容預告:將全力支援Steam掌機
在Kafka引入Replication之後,同一個Partition可能會有多個Replica,而這時需要在這些Replication之間選出一個Leader,Producer和Consumer只與這個Leader互動,其它Replica作為Follower從Leader中複製資料。
因為需要保證同一個Partition的多個Replica之間的資料一致性(其中一個宕機後其它Replica必須要能繼續服務並且即不能造成資料重複也不能造成資料丟失)。如果沒有一個Leader,所有Replica都可同時讀/寫資料,那就需要保證多個Replica之間互相(N×N條通路)同步資料,資料的一致性和有序性非常難保證,大大增加了Replication實現的複雜性,同時也增加了出現異常的機率。而引入Leader後,只有Leader負責資料讀寫,Follower只向Leader順序Fetch資料(N條通路)
kafka HA設計解析
Replication分配
Kafka分配Replica的演算法如下:
1.將所有Broker(假設共n個Broker)和待分配的Partition排序
2.將第i個Partition分配到第(i % n)個Broker上
3.將第i個Partition的第j個Replica分配到第((i + j) % n)個Broker上
使同一個Partition的Replica儘量分散到不同Broker服務上,保證該Partition的高可用
Data Replication(副本策略)
-
訊息傳遞同步策略
Producer在釋出訊息到某個Partition時,先通過ZooKeeper找到該Partition的Leader,Producer只將該訊息傳送到該Partition的Leader。Leader會將該訊息寫入其本地Log。每個Follower都從Leader pull資料。這種方式上,Follower儲存的資料順序與Leader保持一致。Follower在收到該訊息並寫入其Log後,向Leader傳送ACK。一旦Leader收到了ISR中的所有Replica的ACK,該訊息就被認為已經commit了,Leader將增加HW並且向Producer傳送ACK。
Consumer讀訊息也是從Leader讀取,只有被commit過的訊息才會暴露給Consumer。
-
ACK前需要保證有多少個備份
對於Kafka而言,定義一個Broker是否“活著”包含兩個條件:
-
一是它必須維護與ZooKeeper的session(這個通過ZooKeeper的Heartbeat機制來實現)。
-
二是Follower必須能夠及時將Leader的訊息複製過來,不能“落後太多”。
Leader會跟蹤與其保持同步的Replica列表,該列表稱為ISR(即in-sync Replica)。如果一個Follower宕機,或者落後太多,Leader將把它從ISR中移除。
Kafka的這種使用ISR的方式則很好的均衡了確保資料不丟失以及吞吐率。Follower可以批量的從Leader複製資料,這樣極大的提高複製效能(批量寫磁碟),極大減少了Follower與Leader的差距。
-
Leader Election演算法
Leader選舉本質上是一個分散式鎖,有兩種方式實現基於ZooKeeper的分散式鎖:
-
節點名稱唯一性:多個客戶端建立一個節點,只有成功建立節點的客戶端才能獲得鎖
-
臨時順序節點:所有客戶端在某個目錄下建立自己的臨時順序節點,只有序號最小的才獲得鎖
Kafka在ZooKeeper中動態維護了一個ISR(in-sync replicas),這個ISR裡的所有Replica都跟上了leader,只有ISR裡的成員才有被選為Leader的可能。
-
如何處理所有Replica都不工作
在ISR中至少有一個follower時,Kafka可以確保已經commit的資料不丟失,但如果某個Partition的所有Replica都宕機了,就無法保證資料不丟失了。這種情況下有兩種可行的方案:
1.等待ISR中的任一個Replica“活”過來,並且選它作為Leader(強一致性)
2.選擇第一個“活”過來的Replica(不一定是ISR中的)作為Leader(高可用性)
-
選舉Leader
在所有broker中選出一個controller,所有Partition的Leader選舉都由controller決定。controller會將Leader的改變直接通過RPC的方式(比ZooKeeper Queue的方式更高效)通知需為此作為響應的Broker。同時controller也負責增刪Topic以及Replica的重新分配。
如果通過ZooKeeper進行通知和選舉(類似哨兵作用),會使ZooKeeper負載過重
HA相關ZooKeeper結構
-
admin
該目錄下znode只有在有相關操作時才會存在,操作結束時會將其刪除
/admin/reassign_partitions用於將一些Partition分配到不同的broker集合上。對於每個待重新分配的Partition,Kafka會在該znode上儲存其所有的Replica和相應的Broker id。該znode由管理程序建立並且一旦重新分配成功它將會被自動移除。
-
brokers
/brokers/ids/[brokerId])儲存“活著”的broker資訊。
topic註冊資訊(/brokers/topics/[topic]),儲存該topic的所有partition的所有replica所在的broker id,第一個replica即為preferred replica,對一個給定的partition,它在同一個broker上最多隻有一個replica,因此broker id可作為replica id。
-
controller
/controller -> int (broker id of the controller)儲存當前controller的資訊
/controller_epoch -> int (epoch)直接以整數形式儲存controller epoch,而非像其它znode一樣以JSON字串形式儲存。