Kafka数据存储详解
1.存儲(chǔ)格式概述
?
-
每一個(gè)partion(文件夾)相當(dāng)于一個(gè)巨型文件被平均分配到多個(gè)大小相等segment(段)數(shù)據(jù)文件里。但每一個(gè)段segment file消息數(shù)量不一定相等,這樣的特性方便old segment fifile高速被刪除。(默認(rèn)情況下每一個(gè)文件大小為1G)
-
每一個(gè)partiton僅僅須要支持順序讀寫即可了。segment文件生命周期由服務(wù)端配置參數(shù)決定。
partiton中segment文件存儲(chǔ)結(jié)構(gòu)
segment fifile組成:由2大部分組成。分別為index file和data file,此2個(gè)文件一一相應(yīng),成對(duì)出現(xiàn),后綴”.index”和“.log”分別表示為segment索引文件、數(shù)據(jù)文件.
segment文件命名規(guī)則:partion全局的第一個(gè)segment從0開始,之后每一個(gè)segment文件名稱為上一個(gè)segment文件最后一條消息的offset值。數(shù)值最大為64位long大小。19位數(shù)字字符長(zhǎng)度,沒(méi)有數(shù)字用0填充。
[root@VM_0_7_centos yfy-0]# ll total 4 -rw-r--r-- 1 root root 10485760 Oct 13 19:37 00000000000000000000.index -rw-r--r-- 1 root root ? ? ? ?0 Oct 13 19:37 00000000000000000000.log -rw-r--r-- 1 root root 10485756 Oct 13 19:37 00000000000000000000.timeindex -rw-r--r-- 1 root root ? ? ? ?8 Oct 13 19:37 leader-epoch-checkpoint2.日志索引
2.1 數(shù)據(jù)文件的分段
數(shù)據(jù)文件以該段中最小的offset命名。這樣在查找指定offset的Message的時(shí)候,用二分查找就可以定位到該Message在哪個(gè)段中。
2.2 偏移量索引
數(shù)據(jù)文件分段使得可以在一個(gè)較小的數(shù)據(jù)文件中查找對(duì)應(yīng)offffset的Message了,但是這依然需要順序掃描才能找到對(duì)應(yīng)offset的Message。為了進(jìn)一步提高查找的效率,Kafka為每個(gè)分段后的數(shù)據(jù)文件建立了索引文件,文件名與數(shù)據(jù)文件的名字是一樣的,只是文件擴(kuò)展名為.index。
?
比如:要查找絕對(duì)offffset為7的Message:
首先是用二分查找確定它是在哪個(gè)LogSegment中,自然是在第一個(gè)Segment中。 打開這個(gè)Segment的index文件,也是用二分查找找到offffset小于或者等于指定offffset的索引條目中最大的那個(gè)offset。自然offset為6的那個(gè)索引是我們要找的,通過(guò)索引文件我們知道offffset為6的Message在數(shù)據(jù)文件中的位置為9807。
打開數(shù)據(jù)文件,從位置為9807的那個(gè)地方開始順序掃描直到找到offset為7的那條Message。
這套機(jī)制是建立在offset是有序的。索引文件被映射到內(nèi)存中,所以查找的速度還是很快的。
一句話,Kafka的Message存儲(chǔ)采用了分區(qū)(partition),分段(LogSegment)和稀疏索引這幾個(gè)手段來(lái)達(dá)到了高效性。
3.日志刪除
Kafka日志管理器允許定制刪除策略。目前的策略是刪除修改時(shí)間在N天之前的日志(按時(shí)間刪除),也可以使用另外一個(gè)策略:保留最后的N GB數(shù)據(jù)的策略(按大小刪除)。為了避免在刪除時(shí)阻塞讀操作,采用了copy-on-write形式的實(shí)現(xiàn),刪除操作進(jìn)行時(shí),讀取操作的二分查找功能實(shí)際是在一個(gè)靜態(tài)的快照副本上進(jìn)行的,這類似于Java的CopyOnWriteArrayList。
Kafka消費(fèi)日志刪除思想:Kafka把topic中一個(gè)parition大文件分成多個(gè)小文件段,通過(guò)多個(gè)小文件段,就容易定期清除或刪除已經(jīng)消費(fèi)完文件,減少磁盤占用。
# 清理超過(guò)指定時(shí)間清理: log.retention.hours=16 # 超過(guò)指定大小后,刪除舊的消息: log.retention.bytes=10737418244.磁盤存儲(chǔ)優(yōu)勢(shì)
Kafka在設(shè)計(jì)的時(shí)候,采用了文件追加的方式來(lái)寫入消息,即只能在日志文件的尾部追加新的消息,并且不允許修改已經(jīng)寫入的消息,這種方式屬于典型的順序?qū)懭氪伺袛嗟牟僮?#xff0c;所以就算是Kafka使用磁盤作為存儲(chǔ)介質(zhì),所能實(shí)現(xiàn)的額吞吐量也非常可觀。
Kafka中大量使用頁(yè)緩存,這也是Kafka實(shí)現(xiàn)高吞吐的重要因素之一。
頁(yè)緩存可以看下面這兩篇博客:
-
聊聊page cache與Kafka之間的事兒:https://www.jianshu.com/p/92f33aa0ff52
-
linux中的頁(yè)緩存和文件IO:https://blog.csdn.net/gdj0001/article/details/80136364
?
Kafka中讀寫message有如下特點(diǎn):
寫message
-
消息從java堆轉(zhuǎn)入page cache(即物理內(nèi)存)。
-
由異步線程刷盤,消息從page cache刷入磁盤。
讀message
-
消息直接從page cache轉(zhuǎn)入socket發(fā)送出去。
-
當(dāng)從page cache沒(méi)有找到相應(yīng)數(shù)據(jù)時(shí),此時(shí)會(huì)產(chǎn)生磁盤IO,從磁盤Load消息到page cache,然后直接從socket發(fā)出去
Kafka高效文件存儲(chǔ)設(shè)計(jì)特點(diǎn)
-
Kafka把topic中一個(gè)parition大文件分成多個(gè)小文件段,通過(guò)多個(gè)小文件段,就容易定期清除或刪除已經(jīng)消費(fèi)完文件,減少磁盤占用。
-
通過(guò)索引信息可以快速定位message和確定response的最大大小。
-
通過(guò)index元數(shù)據(jù)全部映射到memory,可以避免segment file的IO磁盤操作。
-
通過(guò)索引文件稀疏存儲(chǔ),可以大幅降低index文件元數(shù)據(jù)占用空間大小。
總結(jié)
以上是生活随笔為你收集整理的Kafka数据存储详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: git的一些常用命令讲解和开发规范总结
- 下一篇: kafka消费组与重平衡机制详解