持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
概念:
LEO
(log end offset
): 指代下次写入到此Partition
的下一条数据的offset
, 是partition
最大offset+1
HW
(High Water Mark
):Leader partition
同步到其所有follower
的offset
按图解析:
offset = 0 ~ 14
,LEO = 15
:代表最后一条数据后面的offset
,下一次将要写入的数据offset
HW = 8
:offset = 0 ~ 7
已提交数据,offset = 8 ~ 14
未提交数据
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
,可以被消费。
# 默认10000 即 10秒
replica.lag.time.max.ms
# 允许 follower 副本落后 leader 副本的消息数量,超过这个数量后,follower 会被踢出 ISR
replica.lag.max.messages
问题
(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)}
举个栗子:
# 副本有 4 个,1 个 leader 和 3 个 follower
replication-factor = 4
# 最小同步数为3,3个副本写入数据就认为写入成功
min.insync.replicas = 3
(2)在高水位 HW
机制下,Leader
切换时候会发生哪些问题?
会有两个主要问题:
Leader
切换时发生数据丢失问题Leader
切换时发生数据不一致问题
Leader
切换时发生数据丢失问题
此问题发生概率极低。
问题重现流程主要是:
# 副本有 2 个,1 个 leader 和 1 个 follower
replication-factor = 2
# 最小同步数为1,1个副本写入数据就认为写入成功
min.insync.replicas = 1
Leader
给Follower
同步数据Follower
宕机了,又重启了Leader
宕机了,Follower
被选举成Leader
问题重现详细流程:
- 假设一开始:
Leader
的LEO = 1, HW = 0
,Follower
的LEO = 0, HW = 0
- 数据同步:
Follower
发送fetch
请求,Follower
写入数据,Leader
的LEO = 1, HW = 0
,Follower
的LEO = 1, HW = 0
- 数据同步:
Follower
发送fetch
请求,Leader
的LEO = 1, HW = 0
,Follower
的LEO = 1, HW = 0
,这时候Follower
的HW = 1
还没更新 - 这时,
Follower
宕机后重启,Follower
的LEO
会根据HW
自动调整为 0,并把那条数据从日志文件中删除 - 这时,
Leader
宕机了,Follower
被选举为Leader
,之后根据Leader
来同步数据
Leader
切换时发生数据不一致问题
问题重现流程主要是:
# 副本有 2 个,1 个 leader 和 1 个 follower
replication-factor = 2
# 最小同步数为1,1个副本写入数据就认为写入成功
min.insync.replicas = 1
Leader
给Follower
同步数据Follower
宕机了,又重启了Leader
宕机了,Follower
被选举成Leader
- 同步数据
问题重现详细流程:
- 假设一开始:
Leader
的LEO = 2, HW = 1
,Follower
的LEO = 1, HW = 1
- 数据同步:
Follower
发送fetch
请求,Follower
写入数据,Leader
的LEO = 2, HW = 1
,Follower
的LEO = 1, HW = 1
,还没同步完成 - 这时,
Leader
宕机了后重启,Follower
被选举为 新Leader
- 这时,生产者发了一条新数据给 新
Leader
,Leader
的LEO = 2, HW = 2
,Follower
的LEO = 2, HW = 2
,虽然两者HW = 2
,但数据不同。