Kafka數(shù)據(jù)可靠性保證三板斧-ACK/ISR/HW
點(diǎn)擊上方藍(lán)色字體,選擇“設(shè)為星標(biāo)”
回復(fù)”資源“獲取更多資源

為保證producer發(fā)送的數(shù)據(jù),能可靠的發(fā)送到指定的topic,topic的每個(gè)partition收到producer發(fā)送的數(shù)據(jù)后,都需要向producer發(fā)送ack(acknowledgement確認(rèn)收到),如果producer收到ack,就會進(jìn)行下一輪的發(fā)送,否則重新發(fā)送數(shù)據(jù)。
1.副本數(shù)據(jù)同步策略
Kafka選擇了第二種方案(全部完成同步,才發(fā)送ack),原因如下:同樣為了容忍n臺節(jié)點(diǎn)的故障,第一種方案需要2n+1個(gè)副本,而第二種方案只需要n+1個(gè)副本,而Kafka的每個(gè)分區(qū)都有大量的數(shù)據(jù),第一種方案會造成大量數(shù)據(jù)的冗余。
雖然第二種方案的網(wǎng)絡(luò)延遲會比較高,但網(wǎng)絡(luò)延遲對Kafka的影響較小。
Leader維護(hù)了一個(gè)動態(tài)的in-sync replica set (ISR-同步副本列表),意為和leader保持同步的follower集合。當(dāng)ISR中的follower完成數(shù)據(jù)的同步之后,leader就會給follower發(fā)送ack。如果follower長時(shí)間未向leader同步數(shù)據(jù),則該follower將被踢出ISR,該時(shí)間閾值由replica.lag.time.max.ms參數(shù)設(shè)定。Leader發(fā)生故障之后,就會從ISR中選舉新的leader。
ISR(In-Sync Replicas ):與leader保持同步的follower集合
AR(Assigned Replicas):分區(qū)的所有副本
0:producer不等待broker的ack,這一操作提供了一個(gè)最低的延遲,broker一接收到還沒有寫入磁盤就已經(jīng)返回,當(dāng)broker故障時(shí)有可能丟失數(shù)據(jù);
1:producer等待broker的ack,partition的leader落盤成功后返回ack,如果在follower同步成功之前l(fā)eader故障,而由于已經(jīng)返回了ack,系統(tǒng)默認(rèn)新選舉的leader已經(jīng)有了數(shù)據(jù),從而不會進(jìn)行失敗重試,那么將會丟失數(shù)據(jù)

-1(all):producer等待broker的ack,partition的leader和follower全部落盤成功后才返回ack。但是如果在follower同步完成后,broker發(fā)送ack之前,leader發(fā)生故障,導(dǎo)致沒有返回ack給Producer,由于失敗重試機(jī)制,又會給新選舉出來的leader發(fā)送數(shù)據(jù),造成數(shù)據(jù)重復(fù)。
4. HW,LEO,LSO,LW名詞解釋
上圖表示一個(gè)日志文件,這個(gè)日志文件中只有9條消息,第一條消息的offset(LogStartOffset)為0,最后一條消息的offset為8,offset為9的消息使用虛線表示的,代表下一條待寫入的消息。日志文件的 HW 為6,表示消費(fèi)者只能拉取offset在 0 到 5 之間的消息,offset為6的消息對消費(fèi)者而言是不可見的。LEO(log end offset):標(biāo)識當(dāng)前日志文件中已寫入消息的最后一條的下一條待寫入的消息的offset。上圖中offset為9的位置即為當(dāng)前日志文件的 LEO,LEO 的大小相當(dāng)于當(dāng)前日志分區(qū)中最后一條消息的offset值加1.分區(qū) ISR 集合中的每個(gè)副本都會維護(hù)自身的 LEO ,而 ISR 集合中最小的 LEO 即為分區(qū)的 HW,對消費(fèi)者而言只能消費(fèi) HW 之前的消息。
HW(High Watermark):所有副本中最小的LEO, 一個(gè)分區(qū)中所有副本最小的offset,取一個(gè)partition對應(yīng)的ISR中最小的LEO作為HW,consumer最多只能消費(fèi)到HW所在的位置上一條信息。
注意:HW/LEO這兩個(gè)都是指已寫入消息的最后一條的下一條的位置而不是指最后一條的位置。
LSO(Last Stable Offset): 對未完成的事務(wù)而言,LSO 的值等于事務(wù)中第一條消息的位置(firstUnstableOffset),對已完成的事務(wù)而言,它的值同 HW 相同
LW(Low Watermark): 低水位, 代表 AR(分區(qū)中的所有副本)集合中最小的 logStartOffset 值
5.故障處理細(xì)節(jié)
1.follower故障follower發(fā)生故障后會被臨時(shí)踢出ISR,待該follower恢復(fù)后,follower會讀取本地磁盤記錄的上次的HW,并將log文件高于HW的部分截取掉,從HW開始向leader進(jìn)行同步。等該follower的LEO大于等于該P(yáng)artition的HW,即follower追上leader之后,就可以重新加入ISR了。2.leader故障leader發(fā)生故障之后,會從ISR中選出一個(gè)新的leader,之后,為保證多個(gè)副本之間的數(shù)據(jù)一致性,其余的follower會先將各自的log文件高于HW的部分截掉,然后從新的leader同步數(shù)據(jù)。
注意:這只能保證副本之間的數(shù)據(jù)一致性,并不能保證數(shù)據(jù)不丟失或者不重復(fù)。
6.ISR 集合和 HW、LEO的關(guān)系下面具體分析一下 ISR 集合和 HW、LEO的關(guān)系。
假設(shè)某分區(qū)的 ISR 集合中有 3 個(gè)副本,即一個(gè) leader 副本和 2 個(gè) follower 副本,此時(shí)分區(qū)的 LEO 和 HW 都分別為 3 。消息3和消息4從生產(chǎn)者出發(fā)之后先被存入leader副本。
在消息被寫入leader副本之后,follower副本會發(fā)送拉取請求來拉取消息3和消息4進(jìn)行消息同步。在同步過程中不同的副本同步的效率不盡相同,在某一時(shí)刻follower1完全跟上了leader副本而follower2只同步了消息3,如此leader副本的LEO為5,follower1的LEO為5,follower2的LEO 為4,那么當(dāng)前分區(qū)的HW取最小值4,此時(shí)消費(fèi)者可以消費(fèi)到offset0至3之間的消息。
當(dāng)所有副本都成功寫入消息3和消息4之后,整個(gè)分區(qū)的HW和LEO都變?yōu)?,因此消費(fèi)者可以消費(fèi)到offset為4的消息了
由此可見kafka的復(fù)制機(jī)制既不是完全的同步復(fù)制,也不是單純的異步復(fù)制。事實(shí)上,同步復(fù)制要求所有能工作的follower副本都復(fù)制完,這條消息才會被確認(rèn)已成功提交,這種復(fù)制方式極大的影響了性能。而在異步復(fù)制的方式下,follower副本異步的從leader副本中復(fù)制數(shù)據(jù),數(shù)據(jù)只要被leader副本寫入就會被認(rèn)為已經(jīng)成功提交。在這種情況下,如果follower副本都還沒有復(fù)制完而落后于leader副本,然后leader副本宕機(jī),則會造成數(shù)據(jù)丟失。kafka使用這種ISR的方式有效的權(quán)衡了數(shù)據(jù)可靠性和性能之間的關(guān)系。歡迎點(diǎn)贊+收藏+轉(zhuǎn)發(fā)朋友圈素質(zhì)三連
文章不錯?點(diǎn)個(gè)【在看】吧!??


