Leader Epoch
基于HW同步数据
流程说明:
- 集群配置至少写入的副本数为1,min.insync.replicas = 1;
- 初始状态下,副本1(Leader)和副本2(Follower)的LEO和HW均为0;
- 生产者向副本1(Leader)写入2条消息,LEO=2,HW=0;
- 副本2(Follower)向副本1(Leader)拉取消息,携带LEO=0;
- 副本1(Leader)返回2条消息,并携带HW=0;
- 副本2(Follower)接收2条消息,并更新LEO=2;
- Follower副本第二次拉取消息,携带LEO=2,Leader副本接收消息后更新HW=2,返回时携带HW=2,Follower副本接收消息后更新HW=2;
基于HW机制的数据丢失问题
流程说明:
- 初始状态下,副本1(Leader)和副本2(Follower)的LEO=2,HW=1 ;
- 副本2携带LEO=2向副本1发起拉取请求,副本1接收请求后更新自身的HW=2,准备给副本2返回响应,此时副本2所在节点宕机,重启后根据HW将消息2截断;
- 副本2向副本1拉取消息,副本1所在节点宕机,副本2成为Leader;
- 副本1重启后变为Follower副本向副本2发送拉取请求,副本2向副本1返回HW=1,由于Follower副本的HW不能大于Leader副本的HW,副本1将消息2截断,更新HW=1;
此时发生副本1所在节点冲i去后消息2丢失的问题。
基于HW机制的数据不一致问题
流程说明:
- 初始状态下,副本1(Leader):HW=2,LEO=2,副本2(Follower): HW=1,LEO=1;
- 副本1和副本2同时宕机,副本1宕机后未启动,副本2重启后成为Leader;
- 生产者向副本2(Leader)写入一条消息,更新HW=2,LEO=2;
- 副本1所在节点重启,副本1变为Follower副本,由于检测到HW与副本2(Leader)相同,不会再进行日志同步或截断;
步骤4执行完后,副本1(Follower)和副本2(Leader)中消息出现不一致。
Leader Epoch
- Leader Epoch 代表 leader 的纪元信息,初始值为0;
- 每当 leader 变更一次,该值就会加 1 ;
- Leader变更时,每个副本中还会增加一个对应关系:LeaderEpoch -> StartOffset,其中StartOffset 表示该 LeaderEpoch 下写入的第一条消息的偏移量,这个StartOffset也可以理解为上一个LeaderEpoch下副本的 LEO 值;
- 每个副本的Log下都有一个 leader-epoch-checkpoint 文件,在发生 leader epoch 变更时,会将LeaderEpoch -> StartOffset 的对应关系追加到这个文件。
Leader Epoch解决数据丢失问题
流程说明:
- 初始状态下,副本1(Leader)和副本2(Follower)的LE=0,StartOffset=0;
- 副本2(Follower)所在节点宕机,节点重启后不会根据自身的HW进行日志截断,而是向副本1(Leader)请求LEO,请求过程中携带自己的LE;
- 副本1(Leader)返回消息,并携带LEO=2;
- 副本2(Follower)解析响应LEO=2,不会再进行自身的日志截断;
- 副本1(Leader)所在节点宕机,副本2成为Leader,更新LE=1,StartOffset=2。无论副本1所在节点是否重启,生产者消息都会以LE=1追加到副本1中;
Leader Epoch解决数据不一致问题
流程说明:
- 初始状态下,副本1(Leader)有两条消息,HW=2,LEO=1;副本2(Follower)有一条消息,HW=1,LEO=1;两副本均为LE=0,StartOffset=0;
- 副本1和副本2所在节点同时宕机,副本2所在节点随后重启成为Leader,更新LE=1,StartOffset=1;
- 此时生产者向副本2(Leader)写入一条消息,更新HW=2,LEO=2;
- 副本1所在节点重启,副本1变为Follower,向副本2请求LEO,携带自身的LE=0;
- 副本2(Leader)根据携带的LE,找到LE=1对应的StartOffset=1作为LEO返回给副本1(Follower);
- 副本1(Follower)根据LEO=1对自身日志进行截断删除消息2;
- 副本1(Follower)向副本2拉取最新消息进行同步;
副本同步流程
- Leader副本接收生产者写入消息;
- Leader副本将消息写入本地磁盘,更新LEO;
- Follower副本发送数据同步请求,携带自身的LEO和LE;
- Leader副本更新本地保存的其他副本的LEO;
- Leader副本尝试更新isr;
- Leader副本尝试更新HW;
- Leader副本返回Follower副本数据,携带Leader副本的LEO;
- Follower副本接收消息并写入数据,更新自身的LEO;
- Follower副本尝试更新本地的HW;
- isr副本同步完成后,Leader副本更新自身HW,返回生产者成功消息;
零拷贝
- 整个流程包含:两次上下文切换+两个DMA拷贝;
- 零拷贝指的是减少cpu拷贝;
- 生产者(Producer)向kafka生产数据使用mmap,写到mmap中的数据并没有被真正的写到硬盘,操作系统会在程序主动调用flush的时候才把数据真正的写到硬盘;
- Kafka提供参数producer.type来控制是不是主动flush。Kafka写入到mmap之后就立即flush然后再返回生产者(Producer)叫同步(sync),Kafka写入mmap之后立即返回Producer不调用flush叫异步(async);
- 消费者(Consumer)从kafka消费数据采用的是sendfile;