kafka学习:broker数据处理
文章目录
由于历史原因,我们公司用的还是比较老的kafka版本0.10.1.0,最近由于项目需要,学习了kafka的使用,学习过程中了解到的一些知识记录下,以便日后查阅;
1. broker端网络处理模型
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服务处理的入口类;
2.数据写入
kafka数据由索引文件和消息数据组成,而索引文件又有位移索引和时间戳索引;
2.1位移索引
-
索引文件名
索引名:[offset偏移量].index
消息数据名: [offset偏移量].log -
位移索引格式
-
位移索引与消息数据对应关系
上图所记录的是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 - 索引格式
这里的相对位置,对应的是.index索引文件里的相对位移; - 时间戳索引查找过程
时间戳索引文件也是一个稀疏索引文件,要查找某个时间点附近数据时,只能获取第一个不大于该时间点的时间戳索引数据,然后在位移索引里查找实际的消息物理位置;通过该方法查找并不能准确的找到某个时间点的数据;
3. controller
简单来说,controller就是kafka集群的管理者;
一个kafka集群里,某个broker会被选举出来成为controller, 这种选举机制是通过ZK的临时节点(/controller)来实现的;
controller的主要职责有:
- 创建topic
- 删除topic
- 分区重分配
- broker加入集群
- broker崩溃
- …
4. 水印Watermark
实际指的就是位置信息,即位移(offset),kafka源码里用highwatermark,故也称之为高水印;HW:副本最新一条已提交消息的位置,leader的HW决定了consumer能够消费到的最大offset;
LEO:副本中日志下一条待写入消息的offset;
HW和LEO在follower和leader都存在:
- leader的HW是所有副本的最小LEO;
- follower的HW是从leader同步消息fetch时,leader的返回的HW与当前副本的LEO中取较小者;
HW的更新过程如下:
- (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挂掉,则容易出现数据丢失情况;
-
数据不一致:
前置条件:最小同步副本集配置不合理,min.insync.replicase=1
主要原因:follower挂掉后,重新选举为leader, 新插入的数据导致新leader的HW与旧leader的HW相同,但数据不一致;
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 源码解析与实战》