Kafka的儲存機制以及可靠性
一、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實現了唯一標識,但是並沒有提供自帶的去重機制,需要開發人員基於業務規則自己去重。