先来回顾下
LEO和HW的作业。
LEO 作用:
- 负责推算
Leader partition的HW。 - 更新
HW:当所有的follower partition的LEO推送给Leader partition时候,Leader partition根据min{LEO1...LEOn}即可得到Leader的HW
HW 作用:
- 更新
follower的HW:当follower请求leader数据同步时候,leader会返回自己的HW, 然后follower会更新min{Leader(HW),LEO} - 划分已提交和未提交数据:
HW=3,表示前3条数据是已经同步到其他所有的follower里面去了,所以也将其叫做committed(已提交数据),消费者是消费不到HW之后的uncommmitted数据的 - 消费:
Consumer只能看到base offset到HW offset之间的数据,这部分数据是committed,可以被消费。
问题
(1)Leader 跟 Follower 的 HW 和 LEO 如何更新?
Leader 操作:
- 维护所有
follower的LEO值 - 收到
follower请求后,每次返回都会携带HW - 更新
HW: 取各follower的LEO的最小值,即min{LEO1...LEOn} - 更新
LEO: 数据写入一条,此指针就往后移动
Follower 操作:
- 定期向
Leader发送fetch请求同步数据,每个请求都会携带自己的LEO - 更新
LEO: 每次同步数据到follower,都会更新其LEO值 - 更新
HW: 计算方式是min{Leader(HW), 自己的(LEO)}
栗子:
# 副本有 2 个,1 个 leader 和 1 个 follower
replication-factor = 1
- 初始情况:
Leader的HW = 0, LEO = 1,Follower的HW = 0, LEO = 0

-
请求拉取消息:
Follower发送fetch请求Leader收到请求后计算HW:min{Leader(HW), 自己的(LEO)},得到HW = 0- 返回参数携带
HW = 0 Follower收到返回,写入数据,并更新本地LEO

# 这时候 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`
