【Kafka】图解 Leader 跟 Follower 的 HW 和 LEO 如何更新?

681 阅读2分钟

先来回顾下 LEOHW 的作业。

LEO 作用:

  1. 负责推算 Leader partitionHW
  2. 更新 HW:当所有的 follower partitionLEO 推送给 Leader partition 时候,Leader partition 根据 min{LEO1...LEOn} 即可得到 LeaderHW

HW 作用:

  1. 更新 followerHW:当 follower 请求 leader 数据同步时候,leader 会返回自己的 HW, 然后 follower 会更新 min{Leader(HW),LEO}
  2. 划分已提交和未提交数据:HW=3,表示前3条数据是已经同步到其他所有的 follower 里面去了,所以也将其叫做 committed(已提交数据),消费者是消费不到 HW 之后的 uncommmitted 数据的
  3. 消费:Consumer 只能看到 base offsetHW offset 之间的数据,这部分数据是 committed,可以被消费。

问题

(1)LeaderFollowerHWLEO 如何更新?

Leader 操作:

  • 维护所有 follower 的 LEO
  • 收到 follower 请求后,每次返回都会携带 HW
  • 更新 HW 取各 followerLEO 的最小值,即 min{LEO1...LEOn}
  • 更新 LEO 数据写入一条,此指针就往后移动

Follower 操作:

  • 定期Leader 发送 fetch 请求同步数据,每个请求都会携带自己的 LEO
  • 更新 LEO 每次同步数据到 follower,都会更新其 LEO
  • 更新 HW 计算方式是 min{Leader(HW), 自己的(LEO)}

栗子:

# 副本有 2 个,1 个 leader 和 1 个 follower
replication-factor = 1
  1. 初始情况:LeaderHW = 0, LEO = 1FollowerHW = 0, LEO = 0

2022-06-0614-47-01.png

  1. 请求拉取消息:Follower 发送 fetch 请求

    1. Leader收到请求后计算HWmin{Leader(HW), 自己的(LEO)},得到 HW = 0
    2. 返回参数携带 HW = 0
    3. Follower 收到返回,写入数据,并更新本地 LEO

2022-06-0614-57-53.png

# 这时候 Leader 和 follower 的状态是:
Leader  : LEO = 1, HW = 0, ISR 中 follower(B) LEO=0
Follower: LEO = 1, HW = 0# 注意:Leader 和 Follower 副本的 LEO 都是 1,但各自的高水位依然是 0,还没有被更新。
# 它们需要在下一轮的拉取中被更新。

3. 请求拉取消息:Follower 发送 fetch 请求

0.  `Leader`收到请求后计算`HW``min{Leader(HW), 自己的(LEO)}`,得到 `HW = 1`
1.  返回参数携带 `HW = 1`
2.  `Follower` 收到返回,写入数据,并更新本地 `LEO`

2022-06-0615-05-54.png