此處內(nèi)容來自書籍Apache Kafka 實戰(zhàn)一書(作者胡夕)
1Kafka Zookeeper路徑
Kafka中使用到的各個Zookeeper節(jié)點, 路徑如下圖,
即:
2副本和ISR
什么是分區(qū)?
Kafka分區(qū)本質(zhì)上就是一個備份日志, 即利用多份相同的備份共同提供冗余來保持系統(tǒng)高可用性.
什么是副本?
為了保持高可用的備份就是副本.
什么是ISR?
ISR實際上就是Kafka集群動態(tài)維護(hù)的一組同步副本集合(in-sync replicas), 這句話可以讀出來ISR是副本集合, 是與Leader保持同步的副本集合.
實際上每個topic分區(qū)(注意是每個分區(qū)) 都有自己的ISR列表, ISR的所有副本都與leader保持同步狀態(tài), leader副本總是包含在ISR中的, 只有ISR中的副本才有資格被選舉為leader.
什么情況下消息才是已提交?
producer寫入的消息只有被ISR中的所有副本都接受到才被看成是已提交狀態(tài).
高可用能力:
根據(jù)ISR的解釋, 可以知道假設(shè)ISR集合有N個副本, 那么此分區(qū)最多可以忍受N-1個副本崩潰而不丟失已提交消息.
2.1 follower副本同步
leader副本對外提供服務(wù)(讀寫), follower副本僅僅只做向leader副本請求數(shù)據(jù), 從而保持與leader副本的同步.
上圖中的幾個位移:
- 起始位移(base offset): 表示該副本當(dāng)前所含第一條消息的offset
- 高水印值(high watermark, HW): 副本高水印值, 它保存了該副本最新一條已提交消息的位移.leader分區(qū)的HW值確定了Consumer能夠獲取的消息上線, 超過HW值的所有消息都被視為"未提交成功的消息", consumer是看不到的. 另外需要注意的是除了leader副本有HW值之外其他follower副本也都有HW值, 不過只有l(wèi)eader副本的HW值才能決定clients的consumer能夠看到的消息數(shù)量罷了.
- 日志末端位移(log end offset, LEO): 副本日志下一條待寫入消息的offset, 比如此處的LEO是10, 說明(0-9)這10條消息是寫入的, 下一條消息寫入的位移將是序號10. 只有ISR列表中的所有副本都更新了對應(yīng)的LEO之后, leader副本才會向右移動HW值 表名消息寫入成功.
上面可以看到HW和LEO這兩個值很重要, 但是這兩個值leader副本與follower副本更新的方式不太一樣.
2.1.1 LEO更新機制
- 1 Leader副本端的LEO更新:
leader寫log時就會自動更新它自己的LEO值. - 2 Follower更新LEO值:
follower副本只是被動地向leader副本請求數(shù)據(jù), 具體表現(xiàn)為follower副本不停地向leader副本所在的broker發(fā)送FETCH請求, 一旦獲取消息, 便寫入自己的日志中進(jìn)行備份.
Kafka針對follower副本LEO的更新有兩部分:
- LEO值保存在follower副本所在broker的緩存上
- LEO值保存在leader副本所在broker的緩存上. 此處可以理解出leader副本所在機器的緩存上保存了該分區(qū)下所有follower副本的LEO屬性值(當(dāng)然也包括它自己的LEO)
之所以有兩套是因為前者用于幫助follower副本自身更新HW值, 而同時還需要使用后者來確定leader副本的HW值即分區(qū)HW
(1)follower副本端的follower副本LEO何時更新?
在follower發(fā)送FETCH請求后, leader將數(shù)據(jù)返回給follower, 此時follower開始向底層log寫數(shù)據(jù), 從而自動更新其LEO值.
(2)leader副本端的follower副本LEO何時更新?
leader副本段的follower副本LEO的更新發(fā)生在leader處理follower FETCH請求時,一旦leader接收到follower發(fā)送的FETCH請求, 它首先會從自己的log中讀取相應(yīng)的數(shù)據(jù), 但是在給follower返回數(shù)據(jù)之前它先會去更新follower的LEO(即上面所說的第二套LEO值)
2.1.2 HW更新機制
1 follower副本端更新HW
follower更新HW發(fā)生在其更新LEO之后, 一旦follower向log寫完數(shù)據(jù), 它就會嘗試更新HW值. 具體算法即比較當(dāng)前LEO值與FETCH響應(yīng)中l(wèi)eader的HW值, 取兩者之間的最小值作為新的HW值. 因此: 如果follower的LEO值超過了leader的HW值, 那么follower的HW值是不會越過leader HW值的.2 leader副本端更新HW
learder副本端的HW值很重要, 因為它直接影響了分區(qū)數(shù)據(jù)相對于consumer 客戶端的可見性.
leader副本端的HW值的更新 分為正常情況與異常情況兩種:
(1) 正常情況下的更新場景:
A, producer向leader副本寫入消息時: 因為寫入消息會更新leader的LEO,, 故有必要再查看HW值是否也需要更新
B, leader處理follower FETCH 請求時: 當(dāng)leader處理follower的FETCH請求時, 首先會從底層的log讀取數(shù)據(jù), 之后再嘗試更新分區(qū)HW值
(2)異常情況下的更新場景:
A, 副本成為leader副本時: 當(dāng)某個副本成為分區(qū)的leader副本, Kafka會嘗試更新分區(qū)HW. 畢竟分區(qū)leader都發(fā)生了變更, 這個副本的狀態(tài)是一定要檢查的.
B, broker出現(xiàn)崩潰導(dǎo)致副本被剔除ISR時: 若有broker崩潰, 則必須查看是否會波及此分區(qū)(有可能此分區(qū)leader就在這個broker上), 因此檢查分區(qū)HW值是否需要更新是有必要的.