kafka中的高水位
作用:
- 定义消息可见性,用来标志分区下的哪些消息是可以被消费者消费的
- 帮助kafka完成副本同步
高水位:
- 在高水位以下的消息被认为是已提交消息,反之就是未提交消息
- 消费者只能消费已提交消息(这里不讨论事务,因为事务机制会影响消费者所能看到的消息范围,不只是简单依赖高水位来判断,依靠一个名为LSO(log stable offset)的位移值来判断事务型消费者的可见性)
- LOG END OFFET 简写LEO,表示副本写入下一条消息的位移值,
- kafka所有副本都有对应的高水位和LEO值
- kafka使用Leader副本的高水位来定义所在分区的高水位,分区的高水位就是其Leader副本的高水位
高水位更新机制
- broker0上保存了某分区的leader副本和所有Follower副本的LEO
- broekr1上仅仅保存了该分区的某个Follower副本,kafka把broker0保存的这些follower副本成为远程副本
判断与Leader副本保持同步的条件有两个:
- 该远程Follower副本在ISR中
- 该远程Follower副本IEO值落后于Leader副本LEO值的时间,不超过Borker端参数replica.lag.time.max.ms的值,默认值是10s
高水位和LEO更新过程:
Leader副本:
处理生产者请求的逻辑:
- 写入消息到本地磁盘
- 更新分区高水位值:
- 获取Leader副本所在Broker端保存的所有远程副本LEO值
- 获取leader副本高水位值currentHW
- 更新currentHW=max{currentHW,min(LEO-1,LEO-2.........LEO-n)}
处理Follower副本拉取消息的逻辑:
- 读取磁盘(或页缓存)中的消息数据
- 使用Follower副本发送请求中的位置值来更新远程副本LEO值
- 更新分区高水位值currentHW=max{currentHW,min(LEO-1,LEO-2.........LEO-n)}
Follower副本
从leader拉取消息的处理逻辑:
- 写入消息到本地磁盘
- 更新LEO值
- 更新高水位值
- 获取Leader发送的高水位值currentHW
- 获取步骤2 中更新的LEO:currentLEO
- 更新高水位位min(currentHW,currentLEO)
副本同步机制解析
Leader Epoch:大致可以认为是Leader版本,由两部分数据组成
1 Epoch,一个单调增加的版本号,每当副本领导权发生变更时,都会增加该版本号,小版本号的Leader被认为是过期Leader,不能再行使Leader权力
2 起始位移(start Offset),Leader副本在该Epoch值上写入的首条消息的位移
kafka broker会在内存中为每个分区都缓存Leader Epoch数据,同事还会定期的将这些信息持久化到一个checkpoint文件中,当Leader副本写入消息到磁盘时,Broker会尝试更新这部分缓存,如果Leader是首次写入消息,Borker就会想缓存中增减一个Leader Epoch条目,都则就不做更新,每次有Leader变更时,新的Leader副本会查询这部分缓存,取出对应的Leader Epoch的起始位移,以避免数据丢失和不一致的问题
高水位数据会丢失
高水位+leader Epoch:解决broker宕机数据丢失问题