kafka学习:broker数据处理

kafka学习:broker数据处理

文章目录

    • 1. broker端网络处理模型
    • 2.数据写入
      • 2.1位移索引
      • 2.2 时间戳索引
    • 3. controller
    • 4. 水印Watermark
    • 5. ISR
    • 6. 0.11.0之前版本存在的问题
    • 7. 0.11.0之后版本优化方案
    • 8. 参考资料

由于历史原因,我们公司用的还是比较老的kafka版本0.10.1.0,最近由于项目需要,学习了kafka的使用,学习过程中了解到的一些知识记录下,以便日后查阅;

1. broker端网络处理模型

kafka学习:broker数据处理_第1张图片

acceptor:

一个acceptor负责所有新连接;

processors:

acceptor对应多个process thread, 每个process thread负责从连接里读取请求内容和写回数据;

RequestChannel:

processor与handler之间通过request channel通信,processor所有请求都发送到一个request queue里,API thread取到请求后,处理完成后将结果写到respone queue, 每个respone queue与process thread一一对应;

KafkaRequestHandlerPool:

里面包含多个API thread, 线程回调用KafkaApis的handler()方法,KafkaApis是Kafka服务处理的入口类;

kafka学习:broker数据处理_第2张图片

2.数据写入

kafka数据由索引文件和消息数据组成,而索引文件又有位移索引和时间戳索引;

2.1位移索引

  • 索引文件名
    索引名:[offset偏移量].index
    消息数据名: [offset偏移量].log

  • 位移索引格式
    kafka学习:broker数据处理_第3张图片

  • 位移索引与消息数据对应关系
    kafka学习:broker数据处理_第4张图片
    上图所记录的是offset=1234开始的索引,左图1234.index中1,3,5,10分别代表的索引编号和实际消息在1234.log中的位置如下关系:
    索引编号1: offset=1235(1234+1), 消息物理位置=0
    索引编号3: offset=1237(1234+3), 消息物理位置=500

    那么索引offset=1236(索引编号2)的消息物理位置如何处置呢?这里kafka实际用到了稀疏索引原理;
    稀疏索引:每个索引文件只记录了部分索引项,索引项的间隔由broker端参数log.index.interval.bytes确定,默认值是4KB, 即kafka消息.log日志至少写入4B才会增加一个索引项,从这里也可以看出kafka是先记录.log日志后写入.index索引文件;

2.2 时间戳索引

  • 索引文件名
    [offset].timeindex
  • 索引格式
    kafka学习:broker数据处理_第5张图片
    这里的相对位置,对应的是.index索引文件里的相对位移;
  • 时间戳索引查找过程
    kafka学习:broker数据处理_第6张图片
    时间戳索引文件也是一个稀疏索引文件,要查找某个时间点附近数据时,只能获取第一个不大于该时间点的时间戳索引数据,然后在位移索引里查找实际的消息物理位置;通过该方法查找并不能准确的找到某个时间点的数据;

3. controller

简单来说,controller就是kafka集群的管理者;

一个kafka集群里,某个broker会被选举出来成为controller, 这种选举机制是通过ZK的临时节点(/controller)来实现的;

controller的主要职责有:

  • 创建topic
  • 删除topic
  • 分区重分配
  • broker加入集群
  • broker崩溃

4. 水印Watermark

实际指的就是位置信息,即位移(offset),kafka源码里用highwatermark,故也称之为高水印;
kafka学习:broker数据处理_第7张图片
HW:副本最新一条已提交消息的位置,leader的HW决定了consumer能够消费到的最大offset;

LEO:副本中日志下一条待写入消息的offset;

HW和LEO在follower和leader都存在:

  • leader的HW是所有副本的最小LEO;
  • follower的HW是从leader同步消息fetch时,leader的返回的HW与当前副本的LEO中取较小者;

HW的更新过程如下:

kafka学习:broker数据处理_第8张图片

  • (1)follower从leader同步数据,发送fetch请求
  • (2)follower获取到数据后写本地磁盘
  • (3)follower更新当前副本的LEO
  • (4)follower再次从leader同步数据,同时fetch请求里发送自己的LEO
  • (5)leader更新保存的follower LEO
  • (6)leader取所有副本最小的LEO作为HW

5. ISR

ISR, in-sync replicas, kafka集群动态维护的一组同步副本集合;

leader副本总是在ISR列表中,因为,ISR中所有副本都与leader保持同步状态;

如何判断副本的数据是否是同步的呢?

replica.log.time.max.ms,表示follower滞后leader副本的时间间隔,默认值是10s;

6. 0.11.0之前版本存在的问题

主要存在2个问题:数据丢失和数据不一致:

-数据丢失:

前置条件:最小同步副本集配置不合理,min.insync.replicase=1

主要原因:是follower端的HW更新,需要等待fetch返回结果,再更新follower的HW,此时若follwer挂掉,则容易出现数据丢失情况;

kafka学习:broker数据处理_第9张图片

  • 数据不一致:
    前置条件:最小同步副本集配置不合理,min.insync.replicase=1
    主要原因:follower挂掉后,重新选举为leader, 新插入的数据导致新leader的HW与旧leader的HW相同,但数据不一致;
    kafka学习:broker数据处理_第10张图片

7. 0.11.0之后版本优化方案

其实分析上面的0.11.0之前的版本,问题的主要原因有2点:

  • 最小同步副本集配置不合理,min.insync.replicase=1
  • leader重新选举后,不能知道数据是以前leader产生的还是现在的leader产生的

新版0.11.0之后版本优化方案:

引入了leader epoch信息,用epoch表示leader的版本号,从0开始,每当leader更新1次,epoch值就加1

8. 参考资料

  • 《Apache Kafka实战》 胡夕 著
  • 《Kafka 源码解析与实战》

你可能感兴趣的:(kafka)