Kafka 的存儲機制以及可靠性

架構師(JiaGouX)

一、kafka 的存儲機制

kafka 通過 topic 來分主題存放數據,主題內有分區,分區可以有多個副本,分區的內部還細分爲若干個 segment。

所謂的分區其實就是在 kafka 對應存儲目錄下創建的文件夾,文件夾的名字是主題名加上分區編號,編號從 0 開始。

1、segment

所謂的 segment 其實就是在分區對應的文件夾下產生的文件。

一個分區會被劃分成大小相等的若干 segment,這樣一方面保證了分區的數據被劃分到多個文件中保證不會產生體積過大的文件;另一方面可以基於這些 segment 文件進行歷史數據的刪除,提高效率。

一個 segment 又由一個. log 和一個. index 文件組成。

1..log

.log 文件爲數據文件用來存放數據分段數據。

2..index

.index 爲索引文件保存對對應的. log 文件的索引信息。

在. index 文件中,保存了對對應. log 文件的索引信息,通過查找. index 文件可以獲知每個存儲在當前 segment 中的 offset 在. log 文件中的開始位置,而每條日誌有其固定格式,保存了包括 offset 編號、日誌長度、key 的長度等相關信息,通過這個固定格式中的數據可以確定出當前 offset 的結束位置,從而對數據進行讀取。

3.命名規則

這兩個文件的命名規則爲:

partition 全局的第一個 segment 從 0 開始,後續每個 segment 文件名爲上一個 segment 文件最後一條消息的 offset 值,數值大小爲 64 位,20 位數字字符長度,沒有數字用 0 填充。

2、讀取數據

開始讀取指定分區中某個 offset 對應的數據時,先根據 offset 和當前分區的所有 segment 的名稱做比較,確定出數據在哪個 segment 中,再查找該 segment 的索引文件,確定當前 offset 在數據文件中的開始位置,最後從該位置開始讀取數據文件,在根據數據格式判斷結果,獲取完整數據。

二、可靠性保證

1、AR

在 Kafka 中維護了一個 AR 列表,包括所有的分區的副本。AR 又分爲 ISR 和 OSR。

AR = ISR + OSR。

AR、ISR、OSR、LEO、HW 這些信息都被保存在 Zookeeper 中。

1.ISR

ISR 中的副本都要同步 leader 中的數據,只有都同步完成了數據才認爲是成功提交了,成功提交之後才能供外界訪問。

在這個同步的過程中,數據即使已經寫入也不能被外界訪問,這個過程是通過 LEO-HW 機制來實現的。

2.OSR

OSR 內的副本是否同步了 leader 的數據,不影響數據的提交,OSR 內的 follower 盡力的去同步 leader,可能數據版本會落後。

最開始所有的副本都在 ISR 中,在 kafka 工作的過程中,如果某個副本同步速度慢於 replica.lag.time.max.ms 指定的閾值,則被踢出 ISR 存入 OSR,如果後續速度恢復可以回到 ISR 中。

3.LEO

LogEndOffset:分區的最新的數據的 offset,當數據寫入 leader 後,LEO 就立即執行該最新數據。相當於最新數據標識位。

4.HW

HighWatermark:只有寫入的數據被同步到所有的 ISR 中的副本後,數據才認爲已提交,HW 更新到該位置,HW 之前的數據纔可以被消費者訪問,保證沒有同步完成的數據不會被消費者訪問到。相當於所有副本同步數據標識位。

在 leader 宕機後,只能從 ISR 列表中選取新的 leader,無論 ISR 中哪個副本被選爲新的 leader,它都知道 HW 之前的數據,可以保證在切換了 leader 後,消費者可以繼續看到 HW 之前已經提交的數據。

所以 LEO 代表已經寫入的最新數據位置,而 HW 表示已經同步完成的數據,只有 HW 之前的數據才能被外界訪問。

5.HW 截斷機制

如果 leader 宕機,選出了新的 leader,而新的 leader 並不能保證已經完全同步了之前 leader 的所有數據,只能保證 HW 之前的數據是同步過的,此時所有的 follower 都要將數據截斷到 HW 的位置,再和新的 leader 同步數據,來保證數據一致。

當宕機的 leader 恢復,發現新的 leader 中的數據和自己持有的數據不一致,此時宕機的 leader 會將自己的數據截斷到宕機之前的 hw 位置,然後同步新 leader 的數據。宕機的 leader 活過來也像 follower 一樣同步數據,來保證數據的一致性。

2、生產者可靠性級別

通過以上的講解,已經可以保證 kafka 集羣內部的可靠性,但是在生產者向 kafka 集羣發送時,數據經過網絡傳輸,也是不可靠的,可能因爲網絡延遲、閃斷等原因造成數據的丟失。

kafka 爲生產者提供瞭如下的三種可靠性級別,通過不同策略保證不同的可靠性保障。

其實此策略配置的就是 leader 將成功接收消息信息響應給客戶端的時機。

通過 request.required.acks 參數配置:

1:生產者發送數據給 leader,leader 收到數據後發送成功信息,生產者收到後認爲發送數據成功,如果一直收不到成功消息,則生產者認爲發送數據失敗會自動重發數據。

當 leader 宕機時,可能丟失數據。

0:生產者不停向 leader 發送數據,而不需要 leader 反饋成功消息。

這種模式效率最高,可靠性最低。可能在發送過程中丟失數據,也可能在 leader 宕機時丟失數據。

-1:生產者發送數據給 leader,leader 收到數據後要等到 ISR 列表中的所有副本都同步數據完成後,才向生產者發送成功消息,如果一隻收不到成功消息,則認爲發送數據失敗會自動重發數據。

這種模式下可靠性很高,但是當 ISR 列表中只剩下 leader 時,當 leader 宕機讓然有可能丟數據。

此時可以配置 min.insync.replicas 指定要求觀察 ISR 中至少要有指定數量的副本,默認該值爲 1,需要改爲大於等於 2 的值

這樣當生產者發送數據給 leader 但是發現 ISR 中只有 leader 自己時,會收到異常表明數據寫入失敗,此時無法寫入數據,保證了數據絕對不丟。

雖然不丟但是可能會產生冗餘數據,例如生產者發送數據給 leader,leader 同步數據給 ISR 中的 follower,同步到一半 leader 宕機,此時選出新的 leader,可能具有部分此次提交的數據,而生產者收到失敗消息重發數據,新的 leader 接受數據則數據重複了。

3、leader 選舉

當 leader 宕機時會選擇 ISR 中的一個 follower 成爲新的 leader,如果 ISR 中的所有副本都宕機,怎麼辦?

有如下配置可以解決此問題:

unclean.leader.election.enable=false

策略 1:必須等待 ISR 列表中的副本活過來才選擇其成爲 leader 繼續工作。

unclean.leader.election.enable=true

策略 2:選擇任何一個活過來的副本,成爲 leader 繼續工作,此 follower 可能不在 ISR 中。

策略 1,可靠性有保證,但是可用性低,只有最後掛了 leader 活過來 kafka 才能恢復。

策略 2,可用性高,可靠性沒有保證,任何一個副本活過來就可以繼續工作,但是有可能存在數據不一致的情況。

4、kafka 可靠性的保證

At most once:消息可能會丟,但絕不會重複傳輸。

At least once:消息絕不會丟,但可能會重複傳輸。

Exactly once:每條消息肯定會被傳輸一次且僅傳輸一次。

kafka 最多保證 At least once,可以保證不丟,但是可能會重複,爲了解決重複需要引入唯一標識和去重機制,kafka 提供了 GUID 實現了唯一標識,但是並沒有提供自帶的去重機制,需要開發人員基於業務規則自己去重。

作者:挨踢人啊

來源:www.cnblogs.com/itrena/p/8986984.html

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/l8XYVUmdQoBV9rLdkWoLCg