4. Kafka 存储形式
4.1 存储结构

通过上图,我们可以大概了解到一点,Kafka是通过主题进行对数据进行分类的,而一个主题可以划分为多个partition分区,同一topic的不同partition可能分布在不同机器上,进而实现分布式高性能的特点。对于partition在系统中是一个文件夹,其中可能包含多个segment。
我们可以设置segment在内存中的大小,当保存的消息大于segment的大小时,会再建一个segment。一个segment段由三个文件组成,分别为 .log , .index , .timeindex .
topic结构
- topic包含多个partition,
- topic只是逻辑概念,不涉及到存储,partition才是物理概念
- 同一topic的不同partition可能分布在不同机器上
partition结构
- partition是一个文件夹,其中包含多个segment
- 如果其中有n个segment,则共有2*n个文件
- 每个partition是一个有序的队列
- partition中的每条消息都会分配一个有序的id,即offset
segment结构
- 由一对文件组成,一个稀疏索引文件(.index),一个数据文件(.log),一个时间索引文件(.timeindex)
- 文件命名规则
- 上一个segment在partition中的最大offset数值,即,比如00000000000000345678.log文件中的第一条消息的offset为345679
- 最大为64位的long,不足位数补0,如00000000000000345678.log
- 索引文件后缀.index,日志数据文件后缀.log
segment索引文件结构
- 存储一系列的元数据,每条元数据就是一条索引
- 元数据条数小于消息条数,是稀疏索引
- 元数据(即索引)构成
- 索引所指向的message在数据日志文件中的相对序号,即相对的offset,从1开始,该相对offset加上文件名当中的值就是该message在整个partition中的绝对offset了
- 索引所指向的message在数据日志文件中的位置,即文件游标,从0开始,方便直接指定游标打开数据文件
segment日志数据文件结构
- 存储一系列的message
message结构
- offset 偏移量,消息的唯一标识,通过offset能找到唯一消息,类型long 8bytes
- MessageSize 消息长度,类型int32 4bytes
- crc32校验码, 4bytes,校验message
- magic, 表示本次发布kafka服务程序协议版本号 1byte
- attributes 独立版本,标识压缩类型,编码类型 1byte
- key length 4bytes 当key length=-1时,key字段可不写
- key 可选
- payload 实际消息内容
message特点
- message是无状态的,即不会标识是否已被消费过
- message不能同时被多个consumer来消费,可以等前一个消费完成,下一个继续消费。
- consumer可以同时消费多条message
4.2 kafka如何实现高并发存储-如何找到一条需要消费的数据(阿里)
kafka的底层用了稀疏索引的方式,使用了二分查找法,其实很多索引都是二分查找法。 二分查找法的时间复杂度:O(logn)。除了Kafka外,其实 redis,B+树的底层都采用了二分查找法 。
参考: redis的索引底层的 跳表原理 实现 聊聊Mysql索引和redis跳表 —redis的跳表原理 (阿里)
在partition中如何通过offset查找message?
我们都知道,Kafka消费者读取数据时,只需要通过一个offset就可以精准的拉取数据,例如读取offset=368776的message,需要通过下面2个步骤查找。
第一步查找segment file
上述图2为例,
其中第一个文件00000000000000000000.index表示最开始的文件,起始偏移量(offset)为0. 第二个文件00000000000000368769.index的消息量起始偏移量为368770 = 368769 + 1. 同样,第三个文件00000000000000737337.index的起始偏移量为737338=737337 + 1,其他后续文件依次类推,以起始偏移量命名并排序这些文件,只要根据offset 二分查找文件列表,就可以快速定位到具体文件。
当offset=368776时定位到00000000000000368769.index|log
第二步通过segment file查找message
通过第一步定位到segment file,当offset=368776时,依次定位到00000000000000368769.index的元数据物理位置和 00000000000000368769.log的物理偏移地址,然后再通过00000000000000368769.log顺序查找直到 offset=368776为止。
从上述图3可知这样做的优点,segment index file采取稀疏索引存储方式,它减少索引文件大小,通过mmap可以直接内存操作,稀疏索引为数据文件的每个对应message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。
本文详细介绍了Kafka的存储结构,包括topic、partition、segment及其索引文件的组织形式。Kafka通过分布式和分区实现高性能,每个partition由一系列按offset排序的message组成。message查找通过offset在segment文件的稀疏索引中进行二分查找,实现高效定位。文章还探讨了Kafka如何利用这种结构实现高并发存储和消费。
830

被折叠的 条评论
为什么被折叠?



