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.index ,xx.log ,xx.timeindex三个文件组成

三、操作演示
1、创建一个主题

创建一个带有4个分区,2个副本的topic(kafkaData)

./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文件元数据占用空间大小

6、kafka过期消息删除过程

有时候总觉得我的消息没到7天就被删除了,我还以为是我的kafka配置没有生效,了解到 kafka删除机制后才恍然大悟
kafka消息首先由用户设定一个或多个partition,每个partition中kafka会根据消息量来逐步建立多个segment存储消息,每个segment的大小由配置项进行设定,比如这里

log.segment.bytes=1073741824 【1GB】

kafka至少会保留1个工作segment保存消息。消息量超过单个文件存储大小就会新建segment,比如消息量为2.6GB, 就会建立3个segment。kafka会定时扫描非工作segment,将该文件时间和设置的topic过期时间进行对比,如果发现过期就会将该segment文件(具体包括一个log文件和两个index文件)打上.deleted 的标记,如下所示:

-rw-r--r-- 1 root root 1073740353 Nov 13 03:02 00000000000108550131.log.deleted
-rw-r--r-- 1 root root 526304 Nov 13 03:02 00000000000108550131.index.deleted
-rw-r--r-- 1 root root 697704 Nov 13 03:02 00000000000108550131.timeindex.deleted

最后kafka中会有专门的删除日志定时任务过来扫描,发现.deleted文件就会将其从磁盘上删除,释放磁盘空间,至此kafka过期消息删除完成。

可以看出,kafka删除消息是以segment为维度的,而不是以具体的一条条消息为维度。一个segment包含了一段时期的全部消息并存储在一个文件中.删除时是一次性把这个过期的文件包含所有消息全部删除,效率非常高。可以设想如果是先判断一条条的消息时间是否过期再一条条的执行删除,将十分影响kafka的性能和效率,频繁擦除磁盘,对硬盘性能也有较大影响!


所以如果消息量不多没有超过一个segment的存储容量,由于kafka至少要保留一个segment用于存取消息,所以也不会去删除里面过期的消息。实际上,也存在着设置了消息7天过期,但是kafka里面仍存在着10天前的数据,这就是由kafka的删除特性决定的。
 

转载:Kafka的数据存储_郝少的博客-CSDN博客_kafka数据存储在哪里

          kafka消息删除机制_南风知我意丿的博客-CSDN博客_kafka消息清理机制
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值