1. 程式人生 > 遊戲 >《英靈神殿》一週年內容預告:將全力支援Steam掌機

《英靈神殿》一週年內容預告:將全力支援Steam掌機

Replication(主從複製)

在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是否“活著”包含兩個條件:

  1. 一是它必須維護與ZooKeeper的session(這個通過ZooKeeper的Heartbeat機制來實現)。

  2. 二是Follower必須能夠及時將Leader的訊息複製過來,不能“落後太多”。

Leader會跟蹤與其保持同步的Replica列表,該列表稱為ISR(即in-sync Replica)。如果一個Follower宕機,或者落後太多,Leader將把它從ISR中移除。

Kafka的這種使用ISR的方式則很好的均衡了確保資料不丟失以及吞吐率。Follower可以批量的從Leader複製資料,這樣極大的提高複製效能(批量寫磁碟),極大減少了Follower與Leader的差距。

  • Leader Election演算法

Leader選舉本質上是一個分散式鎖,有兩種方式實現基於ZooKeeper的分散式鎖:

  1. 節點名稱唯一性:多個客戶端建立一個節點,只有成功建立節點的客戶端才能獲得鎖

  2. 臨時順序節點:所有客戶端在某個目錄下建立自己的臨時順序節點,只有序號最小的才獲得鎖

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字串形式儲存。