目录
一、基本概念
二、存储位置及格式
1、存储位置
2、分区与存储方式的关系
三、操作演示
1、创建一个主题
2、查看数据目录中的效果
3、向此主题写入大批量数据
4、查看segment file
(1)查看log文件
(2)查看index文件
(3)查看timeindex文件
四、数据存储原理分析
1、说明
2、数据文件建立索引原理
3、数据消费查询原理
4、segment file中索引文件与数据文件的对应关系
5、Kafka高效文件存储设计特点
一、基本概念
1、Broker:消息中间件处理结点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群;
2、Topic:一类消息,Kafka集群能够同时负责多个topic的分发;
3、Partition:topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队;
4、Segment:每个partition又由多个segment file组成;
5、offset:每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。partition中的每个消息都有一个连续的序列号叫做offset,用于partition唯一标识一条消息;
6、message:这个算是kafka文件中最小的存储单位,即是 a commit log。
二、存储位置及格式
1、存储位置
kafka数据的存储位置,在config/server.properties中的log.dirs中配置;
本次演示kafka的日志存储配置为:log.dirs=/tmp/kafka-logs
2、分区与存储方式的关系
partition是以文件的形式存储在文件系统中,比如,创建了一个名为kafkaData的topic,有4个partition,那么在Kafka的数据目录中(由配置文件中的log.dirs指定的)中就有这样4个目录: kafkaData-0, kafkaData-1,kafkaData-2,kafkaData-3,其命名规则为<topic_name>-<partition_id>,里面存储的分别就是这4个partition的数据。
每个数据目录的子目录都有xx.index ,xx.log ,xx.timeindex三个文件组成
三、操作演示
1、创建一个主题
创建一个带有4个分区,2个副本的topic(kafkaData)
[root@master bin]# ./kafka-topics.sh --create --zookeeper master:2181,slaves1:2181,slaves2:2181 --replication-factor 2 --partitions 4 --topic kafkaData
Created topic "kafkaData".
2、查看数据目录中的效果
[root@master kafka-logs]# ls /tmp/kafka-logs/
kafkaData-0
kafkaData-1
[root@slaves1 bin]# ls /tmp/kafka-logs/
kafkaData-1
kafkaData-2
kafkaData-3
[root@slaves2 bin]# ls /tmp/kafka-logs/
kafkaData-0
kafkaData-2
kafkaData-3
由上可以看出kafka的第一个分区kafka-0的两个副本分别在master、slaves2两个节点上;其他同理;
命令查看
[root@master bin]# ./kafka-topics.sh --describe --zookeeper master:2181,slaves1:2181,slaves2:2181 --topic kafkaData
Topic:kafkaData PartitionCount:4 ReplicationFactor:2 Configs:
Topic: kafkaData Partition: 0 Leader: 2 Replicas: 2,0 Isr: 2,0
Topic: kafkaData Partition: 1 Leader: 0 Replicas: 0,1 Isr: 0,1
Topic: kafkaData Partition: 2 Leader: 1 Replicas: 1,2 Isr: 1,2
Topic: kafkaData Partition: 3 Leader: 2 Replicas: 2,1 Isr: 2,1
Leader:指定主分区的broker id;
Replicas: 副本在那些机器上;
Isr:可以做为主分区的broker id;
3、向此主题写入大批量数据
此步骤省略;
4、查看segment file
以kafkaData-0为例:
使用kafka安装bin目录下的kafka-run-class.sh分别查看这些文件的内容:
(1)查看log文件
[root@master bin]# ./kafka-run-class.sh kafka.tools.DumpLogSegments --files /tmp/kafka-logs/kafkaData-0/00000000000000000000.log --print-data-log
...
offset: 7211 position: 448934 CreateTime: 1587632825139 isvalid: true payloadsize: 29 magic: 1 compresscodec: NONE crc: 995429819 payload: 阳光小区,11,1587632825139
offset: 7212 position: 448997 CreateTime: 1587632825139 isvalid: true payloadsize: 28 magic: 1 compresscodec: NONE crc: 2299568067 payload: 单身小区,5,1587632825139
offset: 7213 position: 449059 CreateTime: 1587632825139 isvalid: true payloadsize: 29 magic: 1 compresscodec: NONE crc: 2772987037 payload: 花花小区,12,1587632825139
offset: 7214 position: 449122 CreateTime: 1587632825139 isvalid: true payloadsize: 28 magic: 1 compresscodec: NONE crc: 2369864650 payload: 阳光小区,6,1587632825139
offset: 7215 position: 449184 CreateTime: 1587632825139 isvalid: true payloadsize: 28 magic: 1 compresscodec: NONE crc: 820724779 payload: 单身小区,4,1587632825139
...
payload:为消息体
(2)查看index文件
[root@master bin]# ./kafka-run-class.sh kafka.tools.DumpLogSegments --files /tmp/kafka-logs/kafkaData-0/00000000000000000000.index --print-data-log
...
offset: 1269114 position: 79002134
offset: 1269231 position: 79009410
offset: 1269316 position: 79014708
offset: 1269456 position: 79023419
offset: 1269715 position: 79039540
offset: 1269838 position: 79047192
offset: 1269933 position: 79053095
offset: 1270083 position: 79062430
...
(3)查看timeindex文件
[root@master bin]# ./kafka-run-class.sh kafka.tools.DumpLogSegments --files /tmp/kafka-logs/kafkaData-0/00000000000000000000.timeindex --print-data-log
...
timestamp: 1587632824453 offset: 1867
timestamp: 1587632824473 offset: 1975
timestamp: 1587632824507 offset: 1987
timestamp: 1587632824658 offset: 2657
timestamp: 1587632824759 offset: 3057
timestamp: 1587632824810 offset: 3468
...
注意:
segment file 组成:由2部分组成,分别为index file和data file,这两个文件是一一对应的,后缀”.index”和”.log”分别表示索引文件和数据文件;
segment file 命名规则:partition的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset,ofsset的数值最大为64位(long类型),20位数字字符长度,没有数字用0填充。
四、数据存储原理分析
1、说明
(1)在生产环境中,kafkaData-0下不会只存在一个index、log、timeindex文件;而是像这样:
(2)、我们将index文件称为索引文件,里面存储着大量元数据;log文件称为数据文件,里面存储着大量消息;
2、数据文件建立索引原理
数据文件分段使得可以在一个较小的数据文件中查找对应offset的Message了,但是这依然需要顺序扫描才能找到对应offset的Message。为了进一步提高查找的效率,Kafka为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩展名为.index。
索引文件中包含若干个索引条目,每个条目表示数据文件中一条Message的索引。索引包含两个部分(均为4个字节的数字),分别为相对offset和position。
相对offset:因为数据文件分段以后,每个数据文件的起始offset不为0,相对offset表示这条Message相对于其所属数据文件中最小的offset的大小。举例,分段后的一个数据文件的offset是从20开始,那么offset为25的Message在index文件中的相对offset就是25-20 = 5。存储相对offset可以减小索引文件占用的空间。
position,表示该条Message在数据文件中的绝对位置。只要打开文件并移动文件指针到这个position就可以读取对应的Message了。
3、数据消费查询原理
注意:Messagexxxx抽象表示某条消息具体内容;.log的第二列和.index的第一列表示数据文件中的绝对位置,也就是打开文件并移动文件指针需要指定的地方;
如果我们想要读取offset=368776的message(如图),步骤如下:
(1)查找segment file
00000000000000000000.index表示最开始的文件,起始偏移量(offset)为0.第二个文件00000000000000368769.index的消息量起始偏移量为368770 = 368769 + 1.同样,第三个文件00000000000000737337.index的起始偏移量为737338=737337 + 1,其他后续文件依次类推,以起始偏移量命名并排序这些文件,只要根据offset 二分查找文件列表,就可以快速定位到具体文件。
当offset=368776时定位到00000000000000368769.index|log
(2)通过segment file查找message
通过第一步定位到segment file,当offset=368776时,依次定位到00000000000000368769.index的元数据物理位置和00000000000000368769.log的物理偏移地址,然后再通过00000000000000368769.log顺序查找直到offset=368776为止。
4、segment file中索引文件与数据文件的对应关系
segment的索引文件中存储着大量的元数据,数据文件中存储着大量消息,索引文件中的元数据指向对应数据文件中的message的物理偏移地址。以索引文件中的6,1407
为例,在数据文件中表示第6个message(在全局partition表示第368775个message),以及该消息的物理偏移地址为1407。
5、Kafka高效文件存储设计特点
(1)Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
(2)通过索引信息可以快速定位message和确定response的最大大小。
(3)通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
(4)通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。