上文我們已經學到,
- 一個Topic(主題)會有多個Partition(分區)
- 為了保證高可用,每個分區有多個Replication(副本)
- 副本分為Leader 和 Follower 兩個角色,Follower 從Leader同步數據
- Leader副本對外提供讀寫服務
- 當Leader副本掛掉,從ISR中選一個Follower副本成為新的Leader對外繼續提供服務
- 那么就要保證分區各副本間數據一致性
- 已提交,Leader副本已經被Follower 都同步的消息
- 未提交,Leader已經寫入,還沒有被Follower同步的消息
- 對消費者而言,已提交的消息都可以拿到
- Leader 和 Follower副本上都有HW 和 LEO
- Leader副本除了自己的LEO,還存Follower的LEO
HW (High WaterMarker) 高水位
高水位可以理解為一個橫切面,拉齊分區所有副本已經寫入的消息,保證HW前的消息你有我有全都有啊,水桶原理
這里要注意,所有副本指的是ISR列表中的同步副本,OSR中同步慢的副本不管
LEO (Log End Offset) 日志末端位移
就是分區該副本下一個消息寫入的位移(offset),當前副本最后一條消息的位移是13,下一個消息寫入14位置
Follower 副本何時更新LEO呢?
- 對于Leader副本來說,每次寫入消息,都會更新LEO的值
- Follower 副本不停地向Leader副本發送Fetch請求,一旦獲取數據后就寫入日志文件中進行備份,同時更新LEO值
- 其實Follower跟Leader一樣,寫入數據時更新自己的LEO值
那么Leader 端的Follower的LEO 什么時候更新呢?
- 當Leader接收到Follower發起的Fetch請求
- 先從Log文件中讀取數據
- 先更新Leader中存儲的Follower的LEO
- 再將數據返回給Follower
- 這里會不會存在Leader更新了Follower的LEO,但是Follower實際并沒有收到返回的消息,而造成Follower 所在broker 和 Leader所在broker存的LEO值不一致呢?
Follower 何時更新HW呢?
- Follower寫入數據后,會更新自己的LEO值,然后就嘗試更新自己的HW值
- HW值是怎么算的呢?
- 是根據自己當前LEO值與Leader返回的HW值比較,去較小值作為HW更新
- 這很好理解,Leader中記錄的HW是所有副本HW最小的值,也就是同步最慢的那個副本的LEO,每個副本都需要知道這個事,自己不是最小那就記別人的值
Leader 何時更新HW呢?
- Leader中存儲的HW就是整個分區的HW,直接影響消息對消費者的可見性
- Leader更新HW有4中情況
- Leader接收生產者發送過來的消息,寫入文件后,檢查是否需要更新HW
- Follower副本選舉成為新的Leader是,Kafka會嘗試去更新分區HW
- Broker崩潰,導致副本被踢出ISR,Kafka會檢查分區HW是否有被更新的必要
- Leader處理Follower的Fetch請求是,先從Log讀取數據,然后嘗試跟新HW值
- 正常情況下就是2種: leader處理producer請求,leader處理follower的fetch請求
Leader 的HW值是怎么更新的呢?
- 先選出所有滿足條件的副本,ISR同步副本
- 比較它們的LEO(包括leader的LEO)
- 選擇
最小的LEO值作為HW