因为Producer产生的消息会不断的追加到日志文件的末尾,这样将对消息文件的维护以及以消费的消息的清理带来严重的影响,所以,Kafka引入的分片和索引的设计。每一个Partition对应一个文件夹;“topic名称 分区序号”。每一个Partition分为多个Segment,Segment分为两类文件:“.index”索引文件与“.log”数据文件,其中索引文件和数据文件都在Partition对应的文件夹中。 html
00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log
复制代码
能够看到有索引文件与数据文件,有3个Segment。 这两个文件的命令规则为:Partition全局的第一个Segment从0开始,后续每一个Segment文件名为上一个Segment文件最后一条消息的offset值,数值大小为64位,20位数字字符长度,没有数字用0填充。git
以Segment文件的详细内容: bash
以上图为例,读取offset=170418的消息,首先查找segment文件,其中00000000000000000000.index 为最开始的文件,第二个文件为 00000000000000170410.index(起始偏移为 170410 1=170411),而第三个文件为 00000000000000239430.index(起始偏移为 239430 1=239431),因此这个 offset=170418 就落到了第二个文件之中。其它后续文件能够依次类推,以其偏移量命名并排列这些文件,而后根据二分查找法就能够快速定位到具体文件位置。其次根据 00000000000000170410.index 文件中的 [8,1325] 定位到 00000000000000170410.log 文件中的 1325 的位置进行读取。要是读取 offset=170418 的消息,从 00000000000000170410.log 文件中的 1325的位置进行读取,那么,如何肯定什么时候读完本条消息呢? 这个问题由消息的物理结构解决,消息都具备固定的物理结构,包括:offset(8 Bytes)、消息体的大小(4 Bytes)、crc32(4 Bytes)、magic(1 Byte)、attributes(1 Byte)、key length(4 Bytes)、key(K Bytes)、payload(N Bytes)等等字段,能够肯定一条消息的大小,即读取到哪里截止。分布式
深刻浅出理解基于 Kafka 和 ZooKeeper 的分布式消息队列spa