一、基本概念
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)
[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文件元數據佔用空間大小