當前位置:網站首頁>leader epoch

leader epoch

2022-01-27 14:11:59 程序猿進階

leader epoch 代錶 Leader 的紀元信息(epoch),初始值為0。每當 Leader 變更一次,leader epoch 的值就會加1,相當於為 Leader 增設了一個版本號。每個副本中還會增設一個矢量 <LeaderEpoch >= StartOffset>,其中 StartOffset 錶示當前 LeaderEpoch 下寫入的第一條消息的偏移量

假設有兩個節點A 和 B,B是 leader節點,裏面的數據如圖:

A發生重啟之後,A不是先忙著截斷日志而是先發送 OffsetsForLeaderEpochRequest請求給B,B作為目前的 Leader在收到請求之後會返回當前的 LEO(LogEndOffset,注意圖中 LE0和 LEO的不同),與請求對應的響應為OffsetsForLeaderEpochResponse。如果 A 中的 LeaderEpoch(假設為 LE_A)和 B 中的不相同,那麼 B 此時會查找 LeaderEpoch 為 LE_A+1 對應的 StartOffset 並返回給 A

如上圖所示,A 在收到2之後發現和目前的 LEO 相同,也就不需要截斷日志了,以此來保護數據的完整性。

再如,之後 B 發生了宕機,A 成為新的 leader,那麼對應的 LE=0 也變成了 LE=1,對應的消息 m2 此時就得到了保留。後續的消息都可以以 LE1 為 LeaderEpoch 陸續追加到 A 中。這個時候A就會有兩個LE,第二 LE所記錄的 Offset從2開始。如果B恢複了,那麼就會從 A中獲取到 LE+1的 Offset為 2的值返回給B。

再來看看 LE如何解决數據不一致的問題:當前 A 為 Leader,B 為 Follower,A 中有2條消息 m1 和 m2,而 B 中有1條消息 m1。假設 A 和 B 同時“掛掉”,然後 B 第一個恢複過來並成為新的 leader。

之後 B 寫入消息 m3,並將 LEO 和 HW 更新至2,如下圖所示。注意此時的 LeaderEpoch 已經從 LE0 增至 LE1 了。


緊接著 A 也恢複過來成為 Follower 並向 B 發送 OffsetsForLeaderEpochRequest 請求,此時 A 的 LeaderEpoch 為 LE0。B 根據 LE0 查詢到對應的 offset 為1並返回給 A,A 就截斷日志並删除了消息 m2,如下圖所示。之後 A 發送 FetchRequest 至 B 請求來同步數據,最終A和B中都有兩條消息 m1 和 m3,HW 和 LEO都為2,並且 LeaderEpoch 都為 LE1,如此便解决了數據不一致的問題。

版權聲明
本文為[程序猿進階]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/01/202201271411589935.html

隨機推薦