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文件元數據佔用空間大小

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