Kafka的消息在broker上都是以log的形式進行儲存管理的,本篇主要介紹log的管理,包括log結構、建立、讀寫、分段、清理等。html
Kafka中的Message是以topic爲基本單位組織的,不一樣的topic之間是相互獨立的。每一個partition存儲一部分Message。引用官方的一張圖,能夠直觀地看到topic和partition的關係。git
Partition中的每條Message由offset來表示它在這個partition中的偏移量,這個offset不是該Message在partition數據文件中的實際存儲位置,而是邏輯上一個值,它惟一肯定了partition中的一條Message。所以,能夠認爲offset是partition中Message的id。partition中的每條Message包含了如下三個屬性:github
有多大,data爲message的具體內容。數據庫
在v0版本中,kafka的消息格式以下圖所示:segmentfault
在V1版本中,kakfa的消息格式以下圖所示:服務器
V2版本併發
具體能夠參考下文app
http://www.uml.org.cn/bigdata/2018051731.asp性能
數據文件的分段.net
Kafka解決查詢效率的手段之一是將數據文件分段,好比有100條Message,它們的offset是從0到99。假設將數據文件分紅5段,第一段爲0-19,第二段爲20-39,以此類推,每段放在一個單獨的數據文件裏面,數據文件以該段中最小的offset命名。這樣在查找指定offset的Message的時候,用二分查找就能夠定位到該Message在哪一個段中。
爲數據文件建索引
數據文件分段使得能夠在一個較小的數據文件中查找對應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了。
index文件中並無爲數據文件中的每條Message創建索引,而是採用了稀疏存儲的方式,每隔必定字節的數據創建一條索引。這樣避免了索引文件佔用過多的空間,從而能夠將索引文件保留在內存中。但缺點是沒有創建索引的Message也不能一次定位到其在數據文件的位置,從而須要作一次順序掃描,可是此次順序掃描的範圍就很小了。
下面是一個kafka log dir下的文件分佈:
1)一個Partition Log 對應於一個kafka broker 的log dir下面的一個分區目錄。
2)一個LogSegment對應了partition log directoy下的兩個文件:一個.log文件,一個.index文件。
在一個broker上的log都是經過LogManger來管理的,Kafka 的日誌管理(LogManager)主要的做用是負責日誌的建立、檢索、清理,日誌相關的讀寫操做其實是由日誌實例對象(Log)來處理的。
LogManager 線程是在節點的 Kafka 服務啓動時啓動的,相關代碼以下:
初始化 LogManger 主要有兩個步驟:
雖然使用的是線程池提交任務,併發進行 load 分區日誌,但這個任務自己是阻塞式的,只有當全部的分區日誌加載完成,才能調用 startup() 啓動 LogManager 線程。
KafkaServer 調用 startup()
方法啓動 LogManager 線程,LogManager 啓動後,後臺會運行四個定時任務,代碼實現以下:
四個後臺定時線程的做用:
第一種:delete,即若是LogSegment到期了刪除之,或者LogSegment+此次要添加的消息 > LogSegment的最大容量則刪除最老的的LogSegment
第二種:compact,進行log壓縮,也能夠有效減小日誌文件文件大小,緩解磁盤緊張狀況。
在有些場景中,key和對應的value的值是不斷變化的,就像數據庫的記錄同樣,能夠對同一條記錄進行修改,在kafka中表現就是在某一時刻key=value1,可能在後續某一時刻,添加了一個key=value2的消息,若是消費者只關心最新的值,那麼日誌壓縮就顯得頗有用,以下圖所示:
clean: 表示已經壓縮的部分,壓縮以後,offset是斷斷續續的,不是增量遞增的
dirty: 表示未壓縮部分,offset依然是連續遞增的
https://www.codetd.com/article/1652292
http://www.javashuo.com/article/p-goagrlby-bo.html
https://blog.csdn.net/zhanglh046/article/details/72821483
https://blog.csdn.net/wl044090432/article/details/51008093
http://www.javashuo.com/article/p-wvionlqd-b.html
http://www.uml.org.cn/bigdata/2018051731.asp
http://www.javashuo.com/article/p-cafkmorp-cc.html
---------------------
做者:happy19870612
來源:CSDN
原文:https://blog.csdn.net/zhanglh046/article/details/72821483