KAFKA 服务端日志LEO和HW机制带来的问题及其解决方案

一、KAFKA 服务端日志LEO和HW带来的问题

KAFKA 服务端日志LEO和HW无论是leader还是follow的HW更新都需要第二轮fetch才能完成,若在第二轮fetch中follow或leader崩溃则有可能带来数据丢失或数据不一致问题。

1.1 数据丢失

KAFKA 服务端日志LEO和HW机制带来的问题及其解决方案

该主题有两个副本,其中A是leader,B是follow。设min.insync.replicas=1 and acks=-1则当生产者发送信息后只要leader A 写入到底层,此时kafka就好通知生产者发送成功。

按照现有HW逻辑,fetch第一阶段主要完成leader和follow LEO的更新第二阶段才是HW的更新。在第二阶段首先是leader HW的更新,HW=min(leader leo,follow leo)=2,读取数据后发送给follow B,B收到后正准备更新HW=min(leo=2.leader HW=2)=2但此时B所在broker崩溃。B重启后,因为HW没有更新成功仍然是1故会将LEO截断则LEO=1,offset=1的数据从日志文件删掉。B重启后向A发fetch请求,此时A正好也宕机。则B成为Leader。

当A重启后,按照leader B的hw,A也会进行截断,A上leo=hw=1。最终原来offset=1上的消息从这两个副本都删除,数据永远丢失。

1.2 数据不一致

KAFKA 服务端日志LEO和HW机制带来的问题及其解决方案

二 KAFKA 服务端日志LEO和HW问题解决方案

产生两个问题的原因是HW被作为衡量副本备份成功的关键和崩溃重启后截断的标准,但HW更新是在fetch第二阶段完成,中间充满了不确定性。leader引入了leader epoch,用一对值(epoch,offset),epoch表示leader版本号,每次leader更换就自增一次,offset表示该epoch版本的leader写入第一条消息的位移。每个leader broker都会保存,并定期写入一个文件。当leader写log底层文件时,会尝试更新整个缓存:如这个leader第一次写入则在缓存中增加一条;每个副本成为leader时都会查询这个缓存获取对应版本的位移避免数据丢失和不一致。

KAFKA 服务端日志LEO和HW机制带来的问题及其解决方案

KAFKA 服务端日志LEO和HW机制带来的问题及其解决方案