Log管理機制

Log管理機制

Kafka的消息在broker上都是以log的形式進行儲存管理的,本篇主要介紹log的管理,包括log結構、建立、讀寫、分段、清理等。html

1 前言

Kafka中的Message是以topic爲基本單位組織的,不一樣的topic之間是相互獨立的。每一個partition存儲一部分Message。引用官方的一張圖,能夠直觀地看到topic和partition的關係。git

 

 

2 Kakfa的日誌格式

2.1Partition的數據文件

Partition中的每條Message由offset來表示它在這個partition中的偏移量,這個offset不是該Message在partition數據文件中的實際存儲位置,而是邏輯上一個值,它惟一肯定了partition中的一條Message。所以,能夠認爲offset是partition中Message的id。partition中的每條Message包含了如下三個屬性:github

 

  • l  offset
  • l  MessageSize
  • l  Record
  • l  其中offset爲long型,MessageSize爲int32,表示Record中data

有多大,data爲message的具體內容。數據庫

在v0版本中,kafka的消息格式以下圖所示:segmentfault

 

 

在V1版本中,kakfa的消息格式以下圖所示:服務器

 

 

V2版本併發

 

 

具體能夠參考下文app

http://www.uml.org.cn/bigdata/2018051731.asp性能

 

2.2 Log的分段和索引

數據文件的分段.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也不能一次定位到其在數據文件的位置,從而須要作一次順序掃描,可是此次順序掃描的範圍就很小了。

2.3 log的邏輯結構

  • l  一個Partition Log由多個LogSegment組成
  • l  一個LogSegment表明了整個Partition Log中的某一段,它是由一個FileMessageSet和一個OffsetIndex組成
  • l  FileMessageSet:顧名思義,它表明了一個基於文件的消息集合。內部採用channel方式訪問物理文件。
  • l  OffsetIndex:能夠將其看作一個index table, 每一項表明了一個offset 與 物理文件(.log 文件)position的映射。此外它會與實際的物理文件(.index) 之間是創建的 mmap。
  • l  每個Partition Log有一個nextOffsetMetadata 記錄,用於記錄下一個要添加的messageset的offset
  • l  每個Log都有一個recoverypoint,用於記錄真正flush到磁盤的消息的最後一個offset

2.4 log的物理結構

下面是一個kafka log dir下的文件分佈:

 

 

1)一個Partition Log 對應於一個kafka broker 的log dir下面的一個分區目錄。

2)一個LogSegment對應了partition log directoy下的兩個文件:一個.log文件,一個.index文件。

 

 

 

3 kafka 的日誌管理

在一個broker上的log都是經過LogManger來管理的,Kafka 的日誌管理(LogManager)主要的做用是負責日誌的建立、檢索、清理,日誌相關的讀寫操做其實是由日誌實例對象(Log)來處理的。

3.1 LogManger啓動過程

LogManager 線程是在節點的 Kafka 服務啓動時啓動的,相關代碼以下:

 

 

初始化 LogManger 主要有兩個步驟:

  1. 建立指定的數據目錄,並作相應的檢查:
  • l  確保數據目錄中沒有重複的數據目錄
  • l  數據目錄不存在的話就建立相應的目錄;
  • l  檢查每一個目錄路徑是不是可讀的;
  1. 加載全部的日誌分區,而每一個日誌也會加載該分區全部的 segment 文件,過程比較慢,因此 LogManager 使用線程池的方式,爲每一個日誌的加載都會建立一個單獨的線程。

雖然使用的是線程池提交任務,併發進行 load 分區日誌,但這個任務自己是阻塞式的,只有當全部的分區日誌加載完成,才能調用 startup() 啓動 LogManager 線程。

KafkaServer 調用 startup() 方法啓動 LogManager 線程,LogManager 啓動後,後臺會運行四個定時任務,代碼實現以下:

 

 

四個後臺定時線程的做用:

  • l  cleanupLogs:定時清理過時的日誌 segment,並維護日誌的大小(默認5min);
  • l  flushDirtyLogs:定時刷新將尚未寫到磁盤上日誌刷新到磁盤(默認 無限大);
  • l  checkpointRecoveryPointOffsets:定時將全部數據目錄全部日誌的檢查點寫到檢查點文件中(默認 60s);
  • l  deleteLogs:定時刪除標記爲 delete 的日誌文件(默認 30s)。

3.2 日誌壓縮

第一種:delete,即若是LogSegment到期了刪除之,或者LogSegment+此次要添加的消息 > LogSegment的最大容量則刪除最老的的LogSegment

 

第二種:compact,進行log壓縮,也能夠有效減小日誌文件文件大小,緩解磁盤緊張狀況。

 

在有些場景中,key和對應的value的值是不斷變化的,就像數據庫的記錄同樣,能夠對同一條記錄進行修改,在kafka中表現就是在某一時刻key=value1,可能在後續某一時刻,添加了一個key=value2的消息,若是消費者只關心最新的值,那麼日誌壓縮就顯得頗有用,以下圖所示:

 

 

  • l  # 若是啓用日誌壓縮,並不會針對active log segment,即active log segment不會參加日誌壓縮,只是針對只讀的log segment,避免active log segment成爲熱點,既要讀寫還要壓縮
  • l  # 日誌壓縮的過程是經過多個cleaner線程來完成的,因此咱們能夠經過調整cleaner線程數來併發壓縮性能,減小對整個服務器端的影響
  • l  # 通常狀況下,Log數據量很大,爲了不cleaner線程和其餘業務線程長時間競爭CPU,並不會將active log segment以外的其餘可讀LogSegment在一次壓縮中所有處理掉,而是將這些LogSegment分批處理
  • l  每個log都會被cleanercheckpoint分紅clean和dirty2部分,以下圖所示:

 

 

clean: 表示已經壓縮的部分,壓縮以後,offset是斷斷續續的,不是增量遞增的

dirty: 表示未壓縮部分,offset依然是連續遞增的

  • l  # 每個clean線程根據日誌文件cleanableRatio值來優先壓縮該值較效的log,也就說dirty佔整個日誌的比率越大優先級越高。
  • l  # clean線程在選定須要清理的log後,首先爲dirty部分消息創建一個<key,key對應的last offset>的映射關係,該映射經過SkimpyOffsetMap維護,而後從新複製LogSegment,只保留SkimpyOffsetMap中記錄的消息,拋棄掉其餘消息
  • l  # 通過日誌壓縮後,日誌文件和索引文件會不斷減少,cleaner線程還會對相鄰的LogSegmeng進行合併,避免出現太小的日誌和索引文件

 

 

參考資料:

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://token01.com/2018/03/22/kafka%E6%BA%90%E7%A0%81%E5%89%96%E6%9E%90(%E4%B8%89)%E4%B9%8B%E6%97%A5%E5%BF%97%E7%AE%A1%E7%90%86-LogManager/

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

https://qinzhaokun.github.io/2017/09/10/Kafka%E8%AF%BB%E5%86%99%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AD%98%E5%82%A8%E7%BB%93%E6%9E%84/

 

 

 

 

 

---------------------

做者:happy19870612

來源:CSDN

原文:https://blog.csdn.net/zhanglh046/article/details/72821483

相關文章
相關標籤/搜索