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的数据。

3、每个数据目录的子目录都有xx.indexxx.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文件元数据占用空间大小

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章