從0開始帶你成為Kafka消息中間件高手—第三講
實際上來說,每次leader接收到一條消息,都會更新自己的LEO,也就是log end offset,把最后一位offset + 1,這個大家都能理解吧?接著各個follower會從leader請求同步數據,這是持續進行的
offset = 0 ~ offset = 4,LEO = 5,代表了最后一條數據后面的offset,下一次將要寫入的數據的offset,LEO,你一定要明白他的名詞
然后follower同步到數據之后,就會更新自己的LEO
并不是leader主動推送數據給follower,他實際上是follower主動向leader嘗試獲取數據,不斷的發送請求到leader來fetch最新的數據
然后對于接收到的某一條數據,所有follower的LEO都更新之后,leader才會把自己的HW(High Water Mark)高水位offset + 1,這個高水位offset表示的就是最新的一條所有follower都同步完成的消息
partition中最開始的一條數據的offset是base offset
LEO和HW分別是干什么的呢?
LEO很重要的一個功能,是負責用來更新HW的,就是如果leader和follower的LEO同步了,此時HW就可以更新
所有對于消費者來說,他只能看到base offset到HW offset之間的數據因為只有這之間的數據才表明是所有follower都同步完成的,這些數據叫做“已提交”的,也就是committed,是可以被消費到的
HW offset到LEO之間的數據,是“未提交的”,這時候消費者是看不到的
HW offset表示的是當前已經提交的數據offset,LEO表示的是下一個要寫入的數據的offset
首先leader接收到數據字后就會更新自己的LEO值
接著follower會不斷的向leader發送fetch請求同步數據,然后每次一條數據同步到follower之后,他的LEO就會更新,同時leader發送數據給follower的時候,在leader端會維護所有follower的LEO值
follower發送fetch請求給leader的時候會帶上自己的LEO值,然后leader每次收到一個fetch請求就會更新自己維護的每個follower的LEO值
所以這里大家要知道的是,leader上是會保存所有follower的LEO值的,這個是非常關鍵和核心的一點
每次leader發送數據給follower的時候,都會發送自己的HW值,然后follower獲取到leader HW之后,就會跟自己的LEO比較一下,取里面小的那個值作為自己的HW值,換句話說,如果follower的LEO比leader HW大了,那么follower的HW就是leader HW
但是如果follower的LEO比leader HW小,說明自己明顯落后于leader,那么follower的HW就是自己的LEO值
然后leader上的HW就很明顯了,那就是主要是他在接收follower的fetch請求的時候,就會在更新自己維護的所有follower的LEO之后,判斷一下當前自己的LEO是否跟所有follower都保持一致,那么就會自動更新自己的HW值
這個leader的HW值就是partition的HW值,代表了從這個partition的哪個offset之前可以被消費數據
假設leader收到第一條數據,此時leader LEO = 1,HW = 0,因為他發現其他follower的LEO也是0,所以HW必須是0
接著follower來發送fetch請求給leader同步數據,帶過去follower的LEO = 0,所以leader上維護的follower LEO = 0,更新了一下,此時發現follower的LEO還是0,所以leader的HW繼續是0
接著leader發送一條數據給follower,這里帶上了leader的HW = 0,因為發現leader的HW = 0,此時follower LEO更新為1,但是follower HW = 0,取leader HW
接著下次follower再次發送fetch請求給leader的時候,就會帶上自己的LEO = 1,leader更新自己維護的follower LEO = 1,此時發現follower跟自己的LEO同步了,那么leader的HW更新為1
接著leader發送給follower的數據里包含了HW = 1,此時follower發現leader HW = 1,自己的LEO = 1,此時follower的HW有更新為1
5個數據:全部都要往前推進更新,需要2次請求,第一次請求是僅僅是更新兩邊的LEO,第二次請求是更新另外leader管理的follower LEO,以及兩個HW