Kafka 高级架构
一 .简介
kafka
的 topic 被分为多个分区,分区的数据是按照Segments
也就是分段来存储文件块。分区日志是存储在磁盘上的日志序列。kafka
可以保证的是一个分区里面的事件是有序的。其中 leader 负责对应分区的读写。Follower负责同步分区的数据。0.11 版本之前 kafka
使用的是highwatermarker机制
来保证数据放入同步,但是基于highwatermarker
的同步数据可能会导致数据的不一致和数据乱序
LEO
: log end offset
标识的是每个分区中最后一条消息的下一个位置,分区的每一个副本都是有自己的LEO
HW
: high watermarker
高水位线 ,所有的HW
之前的数据都是可以理解为已经备份了,所有节点都备份成功的时候,Leader会更新HW
;
ISR
:in-sync-replicas kafka
的leader 会维护一份处于同步的副本集合,如果在配置 replica.lag.time.max.ms
时间内系统没发送fetch 请求,或者在发送请求中(replica.lag.max.message
),但是在制定的时间内数据也和leader数据不一致,相差个数 replica.lag.max.message
就会被剔除出ISR
列表 ;相当于就是说主机里面维护的就是支持的follower ,一旦就是主机宕机的话,可以在ISR
列表中可以选出一个可用主机;但是在0.9.0 版本后去掉了 replica.lag.max.message
只保留了前者;
二.kafka-0.11
版本之前
数据同步已经存在的问题
情况1:数据丢失
情况2:数据不一致
三.kafka-0.11
版本+版本改进
在 0.11 版本之前的副本备份机制设计是存在一定的问题的。存在数据丢失和数据不一致的问题,在0.11 版本之后,不在使用HW
作为数据截断的依据, 引入了Leader Epoch
解决这个问题,任意一个Leader 持有一个LeaderEpoch
,LeaderEpoch
是由Controller
管理的32位数字,存储在zookeeper
的分区状态信息中,并作为LeaderAndIsrRequest
传递到每一个新产生的Leader。Leader 接受生产者数据是,使用LeaderEpoch
标记每一个message ,然后该LeaderEpoch
编号通过复制协议广播,用于替换原有的HW
,作为新的截断信息的参考点;
改进消息格式: 每个消息都携带一个4字节的 LeaderEpoch
号,并且在日志目录中创建一个Leader Epoch sequence
文件,里面存储的是 LeaderEpoch
的序列号和在该epoch 中生产消息的Start Offset
,会缓存在每一个副本中,和内存中;
当follower 变成 leader:首先是新的LeaderEpoch
和副本的LEO 添加到 Leader Epoch sequence
文件的末尾并刷新数据,新的Leader产生的数据都带有新的 LeaderEpoch
的标记;
当leader 变成 follower:加载本地Leader Epoch sequence
文件 ,对响应的分区Leader发送 epoch 请求
(当前最新的EpochID ,Start Offset
,虽然是最新的,也就是follower 之前的,一般可能是上一个EpochID
),获取最新的 LeaderEpoch
信息(EpochID,Start Offset
); Leader 接受到消息后返回该 EpochID
对应的LastOffset
。 该消息可能是最新的EpochID
的StartOffset
或者是当前的EpochID
的LEO 信息(follower->follower)
情况1:follower
的 Offset 比Leader小;follower在提取过程中 如自己的果LeaderEpoch
的消息大于Leader 的 LeaderEpoch
,则会在其 Leader Epoch sequence
添加,并刷新到磁盘,同时fetch 日志属性到本地日志文件
情况2:follower
的 LeaderEpoch
信息比Leader 返回的 LastOffset
大 Follower 要去重置自己的 LeaderEpoch
。将 Offset 修改为Leader的LastOffset
,并截断自己的日志信息
四.epoch 解决
1.处理数据丢失
2.处理数据不一致