閱讀354 返回首頁    go 阿裏雲 go 技術社區[雲棲]


解析Kafka High Available

Kafka在HA架設需要兩個內容

Replication (主從複製)
Leader Election     (從屬選取主級)
在Kafka在0.8以前的版本中,是沒有Replication(主從控製)的,一旦某一個Broker(服務器節點)宕機,則其上所有的Partition(topic分區)數據都不可被消費,這與Kafka數據持久性及Delivery Guarantee(消息消費保障的設計目標相悖。同時Producer(生產者)都不能再將數據存於這些Partition(topic分區)中。

一、如何進行Replication主從複製:

1、如何把replica均勻的分布到集群中的每一個或者大多數的節點上(broke)

可以從前麵的文章回到一個事實,為了能夠提高整個集群的性能需要吧同一個topic下麵的所有partition盡可能的分布到整個集群上去,一個典型的解決方案就是topic的partition的數量大於broke的數量.同樣的,為了提高卡夫卡的HA,我們需要吧同一個partitio下麵的所有replica(備份)盡量的分散到不同的服務器上去.(事實上,如果我們把某一個partition的所有replica全部放到同一個broker上那麼同樣的這個broker宕機了,也就回到這這個partition下麵的所有信息丟失,沒有起到HA的效驗)

2、kafka分派replica算法:

分配條件
    N 個broker
    x 個 partition
    y 個replica
分配方式
    將所有的broker和所有的partition進行排序
    把第i個partition分配到 [i [ mod] n](i 除以 你的餘數)(就是從第一台broker上開始部署,部署到最後一台broker,如果還沒部署完,怎進行循環)個broker上(分配topic的分區的部署位置)
    把第i個partition的第j個replica分配到[(i+j) mod n]個broker上,效果和上年的分配partition是一樣的.

3、如何進行主從數據propagate

有一個前提,product生產的消息隻是和partition的leader進行通信,是不關心partition是有多少個replica的.
    product在發布消息到partition時,先通過zookeeper找到該partition的leader
    leader把數據寫入log
    所有的follower都從leader pull拉去數據,而後寫入這些follower的log裏麵
    通過pull的方式可以保證replica的消息順序是和其leader的消息順序一致
    然後每個follower都向leader發送ACK
    一但leader收到ISR(同步列表)的所有ACK,則認為該條消息已經被commit了

4、為了保住高吞吐量,kafka同樣對replication的過程做了優化,
過程不是純同步(性能會很忙),也不是純異步(消息會丟失)

kafka采用了ISR列表的方式來進行維護
    ISR列表標識in-sync Replica 其意義為:與leader保持同步的Replica列表
    如果一個Follower宕機,或者落後太多,Leader將把它從ISR中移除。
    Kafka處理失敗需要明確定義一個Broker是否“活著”。對於Kafka而言,Kafka存活包含兩個條件,一是它必須維護與ZooKeeper session(這個通過ZooKeeper的Heartbeat機製來實現)。二是Follower必須能夠及時將Leader的消息複製過來,不能“落後太多”。

二、如何保證給product ACK之前的備份數量
1、需要說明的是,Kafka隻解決fail/recover,不處理“Byzantine”(“拜占庭”)問題。
2、一條消息隻有被ISR裏的所有Follower都從Leader複製過去才會被認為已提交。
3、而對於Producer而言,它可以選擇是否等待消息commit,這可以通過request.required.acks來設置。
4、這種機製確保了隻要ISR有一個或以上的Follower,一條被commit的消息就不會丟失。

三、如何進行Leader Election

1、使用的選舉Leader方式

Kafka在ZooKeeper中動態維護了一個ISR(in-syncreplicas),這個ISR裏的所有Replica都跟上了leader,隻有ISR裏的成員才有被選為Leader的可能。
        在這種模式下,對於f+1個Replica,一個Partition能在保證不丟失已經commit的消息的前提下容忍f個Replica的失敗。在大多數使用場景中,這種模式是非常有利的。

四、如何處理所有的replica都宕機了

1、等待ISR中的任一個Replica“活”過來,並且選它作為Leader
2、選擇第一個“活”過來的Replica(不一定是ISR中的)作為Leader

五、如何選舉leader

1、它在所有broker中選出一個controller,所有Partition的Leader選舉都由controller決定。
**2、controller會將Leader的改變直接通過RPC的方式(比ZooKeeper Queue的方式更高效)通知需為為此作為響應的Broker。
3、同時controller也負責增刪Topic以及Replica的重新分配。
**

六、節點故障企切換過程(broker failover)

1. Controller在ZooKeeper注冊Watch,一旦有Broker宕機(這是用宕機代表任何讓係統認為其die的情景,包括但不限於機器斷電,網絡不可用,GC導致的Stop The World,進程crash等),其在ZooKeeper對應的znode會自動被刪除,ZooKeeper會fire Controller注冊的watch,Controller讀取最新的幸存的Broker。
2. Controller決定set_p,該集合包含了宕機的所有Broker上的所有Partition。

3. 對set_p中的每一個Partition

3.1 從/brokers/topics/[topic]/partitions/[partition]/state讀取該Partition當前的ISR
3.2 
決定該Partition的新Leader。
如果當前ISR中有至少一個Replica還幸存,則選擇其中一個作為新Leader,新的ISR則包含當前ISR中所有幸存的Replica。
否則選擇該Partition中任意一個幸存的Replica作為新的Leader以及ISR(該場景下可能會有潛在的數據丟失)。
        如果該Partition的所有Replica都宕機了,則將新的Leader設置為-1。
3.3 將新的Leader,ISR和新的leader_epoch及controller_epoch寫入/brokers/topics/[topic]/partitions/[partition]/state。
注意,該操作隻有其version在3.1至3.3的過程中無變化時才會執行,否則跳轉到3.1

4. 直接通過RPC向set_p相關的Broker發送LeaderAndISRRequest命令。Controller可以在一個RPC操作中發送多個命令從而提高效率。

核心內容以及數據結構請查看該博客

最後更新:2017-11-14 16:34:24

  上一篇:go  《maven實戰》讀書筆記6——maven聚合和繼承
  下一篇:go  U盤數據丟失了怎麼免費恢複教程-快速有效