在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分配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的高可用
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。
對於kafka而言,定義乙個broker是否「活著」包含兩個條件:
一是它必須維護與zookeeper的session(這個通過zookeeper的heartbeat機制來實現)。
二是follower必須能夠及時將leader的訊息複製過來,不能「落後太多」。
leader會跟蹤與其保持同步的replica列表,該列表稱為isr(即in-sync replica)。如果乙個follower宕機,或者落後太多,leader將把它從isr中移除。
kafka的這種使用isr的方式則很好的均衡了確保資料不丟失以及吞吐率。follower可以批量的從leader複製資料,這樣極大的提高複製效能(批量寫磁碟),極大減少了follower與leader的差距。
leader選舉本質上是乙個分布式鎖,有兩種方式實現基於zookeeper的分布式鎖:
節點名稱唯一性:多個客戶端建立乙個節點,只有成功建立節點的客戶端才能獲得鎖
臨時順序節點:所有客戶端在某個目錄下建立自己的臨時順序節點,只有序號最小的才獲得鎖
kafka在zookeeper中動態維護了乙個isr(in-sync replicas),這個isr裡的所有replica都跟上了leader,只有isr裡的成員才有被選為leader的可能。
在isr中至少有乙個follower時,kafka可以確保已經commit的資料不丟失,但如果某個partition的所有replica都宕機了,就無法保證資料不丟失了。這種情況下有兩種可行的方案:
1.等待isr中的任乙個replica「活」過來,並且選它作為leader(強一致性)
2.選擇第乙個「活」過來的replica(不一定是isr中的)作為leader(高可用性)
在所有broker中選出乙個controller,所有partition的leader選舉都由controller決定。controller會將leader的改變直接通過rpc的方式(比zookeeper queue的方式更高效)通知需為此作為響應的broker。同時controller也負責增刪topic以及replica的重新分配。
如果通過zookeeper進行通知和選舉(類似哨兵作用),會使zookeeper負載過重
該目錄下znode只有在有相關操作時才會存在,操作結束時會將其刪除
/admin/reassign_partitions用於將一些partition分配到不同的broker集合上。對於每個待重新分配的partition,kafka會在該znode上儲存其所有的replica和相應的broker id。該znode由管理程序建立並且一旦重新分配成功它將會被自動移除。
/brokers/ids/[brokerid])儲存「活著」的broker資訊。
topic註冊資訊(/brokers/topics/[topic]),儲存該topic的所有partition的所有replica所在的broker id,第乙個replica即為preferred replica,對乙個給定的partition,它在同乙個broker上最多只有乙個replica,因此broker id可作為replica id。
/controller -> int (broker id of the controller)儲存當前controller的資訊
/controller_epoch -> int (epoch)直接以整數形式儲存controller epoch,而非像其它znode一樣以json字串形式儲存。
Kafka高可用實現
資料儲存格式 kafka的高可靠性的保障 於其健壯的副本 replication 策略。乙個topic可以分成多個partition,而乙個partition物理上由多個segment組成。segment分2部分 索引檔案和資料檔案。索引檔案儲存元資料,記錄了訊息在資料檔案中的偏移 offset 訊...
Kafka如何保證高可用
kafka 乙個最基本的架構認識 由多個 broker 組成,每個 broker 是乙個節點 你建立乙個 topic,這個 topic 可以劃分為多個 partition,每個 partition 可以存在於不同的 broker 上,每個 partition 就放一部分資料。如果用rabbitmq來...
kafka是如何實現高可用的
kafka面試中,經常會被問到kafka是如何實現高可用的。ha,也就是高可用,kafka 0.8版本之前是沒有ha的,如果乙個broker掛了,那麼這個分割槽也就是掛了,分區內的訊息都沒辦法繼續被消費。kafka 0.8版本之後引入了副本機制 replicas 副本機制也是分布式系統中的常用的機制...