【轉】kafka-檔案儲存機制詳解
文章轉自“美團技術部落格”:https://tech.meituan.com/
Kafka是什麼
Kafka是最初由Linkedin公司開發,是一個分散式、分割槽的、多副本的、多訂閱者,基於zookeeper協調的分散式日誌系統(也可以當做MQ系統),常見可以用於web/nginx日誌、訪問日誌,訊息服務等等,Linkedin於2010年貢獻給了Apache基金會併成為頂級開源專案。
1.前言
一個商業化訊息佇列的效能好壞,其檔案儲存機制設計是衡量一個訊息佇列服務技術水平和最關鍵指標之一。
下面將從Kafka檔案儲存機制和物理結構角度,分析Kafka是如何實現高效檔案儲存,及實際應用效果。
2.Kafka檔案儲存機制
Kafka部分名詞解釋如下:
-
Broker:訊息中介軟體處理結點,一個Kafka節點就是一個broker,多個broker可以組成一個Kafka叢集。
-
Topic:一類訊息,例如page view日誌、click日誌等都可以以topic的形式存在,Kafka叢集能夠同時負責多個topic的分發。
-
Partition:topic物理上的分組,一個topic可以分為多個partition,每個partition是一個有序的佇列。
-
Segment:partition物理上由多個segment組成,下面2.2和2.3有詳細說明。
-
offset:每個partition都由一系列有序的、不可變的訊息組成,這些訊息被連續的追加到partition中。partition中的每個訊息都有一個連續的序列號叫做offset,用於partition唯一標識一條訊息.
分析過程分為以下4個步驟:
-
topic中partition儲存分佈
-
partiton中檔案儲存方式
-
partiton中segment檔案儲存結構
-
在partition中如何通過offset查詢message
通過上述4過程詳細分析,我們就可以清楚認識到kafka檔案儲存機制的奧祕。
2.1 topic中partition儲存分佈
假設實驗環境中Kafka叢集只有一個broker,xxx/message-folder為資料檔案儲存根目錄,在Kafka broker中server.properties檔案配置(引數log.dirs=xxx/message-folder),例如建立2個topic名稱分別為report_push、launch_info, partitions數量都為partitions=4
儲存路徑和目錄規則為:
xxx/message-folder
|--report_push-0
|--report_push-1
|--report_push-2
|--report_push-3
|--launch_info-0
|--launch_info-1
|--launch_info-2
|--launch_info-3
在Kafka檔案儲存中,同一個topic下有多個不同partition,每個partition為一個目錄,partiton命名規則為topic名稱+有序序號,第一個partiton序號從0開始,序號最大值為partitions數量減1。
如果是多broker分佈情況下:
下面以一個Kafka叢集中4個Broker舉例,建立1個topic包含4個Partition,2 Replication;資料Producer流動如圖所示:
(1)
(2)當叢集中新增2節點,Partition增加到6個時分佈情況如下:
副本分配邏輯規則如下:
-
在Kafka叢集中,每個Broker都有均等分配Partition的Leader機會。
-
上述圖Broker Partition中,箭頭指向為副本,以Partition-0為例:broker1中parition-0為Leader,Broker2中Partition-0為副本。
-
上述圖種每個Broker(按照BrokerId有序)依次分配主Partition,下一個Broker為副本,如此迴圈迭代分配,多副本都遵循此規則。
副本分配演算法如下:
-
將所有N Broker和待分配的i個Partition排序.
-
將第i個Partition分配到第(i mod n)個Broker上.
-
將第i個Partition的第j個副本分配到第((i + j) mod n)個Broker上.
2.2 partiton中檔案儲存方式
下面示意圖形象說明了partition中檔案儲存方式:
圖1
-
每個partion(目錄)相當於一個巨型檔案被平均分配到多個大小相等segment(段)資料檔案中。但每個段segment file訊息數量不一定相等,這種特性方便old segment file快速被刪除。
-
每個partiton只需要支援順序讀寫就行了,segment檔案生命週期由服務端配置引數決定。
這樣做的好處就是能快速刪除無用檔案,有效提高磁碟利用率。
2.3 partiton中segment檔案儲存結構
讀者從2.2節瞭解到Kafka檔案系統partition儲存方式,本節深入分析partion中segment file組成和物理結構。
-
segment file組成:由2大部分組成,分別為index file和data file,此2個檔案一一對應,成對出現,字尾".index"和“.log”分別表示為segment索引檔案、資料檔案.
-
segment檔案命名規則:partion全域性的第一個segment從0開始,後續每個segment檔名為上一個segment檔案最後一條訊息的offset值。數值最大為64位long大小,19位數字字元長度,沒有數字用0填充。
下面檔案列表是筆者在Kafka broker上做的一個實驗,建立一個topicXXX包含1 partition,設定每個segment大小為500MB,並啟動producer向Kafka broker寫入大量資料,如下圖2所示segment檔案列表形象說明了上述2個規則:
圖2
以上述圖2中一對segment file檔案為例,說明segment中index<—->data file對應關係物理結構如下:
圖3
上述圖3中索引檔案儲存大量元資料,資料檔案儲存大量訊息,索引檔案中元資料指向對應資料檔案中message的物理偏移地址。
其中以索引檔案中元資料3,497為例,依次在資料檔案中表示第3個message(在全域性partiton表示第368772個message)、以及該訊息的物理偏移地址為497。
從上述圖3瞭解到segment data file由許多message組成,下面詳細說明message物理結構如下:
圖4
引數說明:
關鍵字 |
解釋說明 |
8 byte offset |
在parition(分割槽)內的每條訊息都有一個有序的id號,這個id號被稱為偏移(offset),它可以唯一確定每條訊息在parition(分割槽)內的位置。即offset表示partiion的第多少message |
4 byte message size |
message大小 |
4 byte CRC32 |
用crc32校驗message |
1 byte “magic" |
表示本次釋出Kafka服務程式協議版本號 |
1 byte “attributes" |
表示為獨立版本、或標識壓縮型別、或編碼型別。 |
4 byte key length |
表示key的長度,當key為-1時,K byte key欄位不填 |
K byte key |
可選 |
value bytes payload |
表示實際訊息資料 |
2.4 在partition中如何通過offset查詢message
例如讀取offset=368776的message,需要通過下面2個步驟查詢。
-
第一步查詢segment file
上述圖2為例,其中00000000000000000000.index表示最開始的檔案,起始偏移量(offset)為0.第二個檔案00000000000000368769.index的訊息量起始偏移量為368770 = 368769 + 1.同樣,第三個檔案00000000000000737337.index的起始偏移量為737338=737337 + 1,其他後續檔案依次類推,以起始偏移量命名並排序這些檔案,只要根據offset **二分查詢**檔案列表,就可以快速定位到具體檔案。
當offset=368776時定位到00000000000000368769.index|log
-
第二步通過segment file查詢message
通過第一步定位到segment file,當offset=368776時,依次定位到00000000000000368769.index的元資料物理位置和00000000000000368769.log的物理偏移地址,然後再通過00000000000000368769.log順序查詢直到offset=368776為止。
從上述圖3可知這樣做的優點,segment index file採取稀疏索引儲存方式,它減少索引檔案大小,通過mmap可以直接記憶體操作,稀疏索引為資料檔案的每個對應message設定一個元資料指標,它比稠密索引節省了更多的儲存空間,但查詢起來需要消耗更多的時間。
3 Kafka檔案儲存機制–實際執行效果
實驗環境:
-
Kafka叢集:由2臺虛擬機器組成
-
cpu:4核
-
實體記憶體:8GB
-
網絡卡:千兆網絡卡
-
jvm heap: 4GB
-
詳細Kafka服務端配置及其優化請參考:kafka server.properties配置詳解
圖5
從上述圖5可以看出,Kafka執行時很少有大量讀磁碟的操作,主要是定期批量寫磁碟操作,因此操作磁碟很高效。這跟Kafka檔案儲存中讀寫message的設計是息息相關的。Kafka中讀寫message有如下特點:
寫message
-
訊息從java堆轉入page cache(即實體記憶體)。
-
由非同步執行緒刷盤,訊息從page cache刷入磁碟。
讀message
-
訊息直接從page cache轉入socket傳送出去。
-
當從page cache沒有找到相應資料時,此時會產生磁碟IO,從磁
盤Load訊息到page cache,然後直接從socket發出去
4.總結
Kafka高效檔案儲存設計特點
-
Kafka把topic中一個parition大檔案分成多個小檔案段,通過多個小檔案段,就容易定期清除或刪除已經消費完檔案,減少磁碟佔用。
-
通過索引資訊可以快速定位message和確定response的最大大小。
-
通過index元資料全部對映到memory,可以避免segment file的IO磁碟操作。
-
通過索引檔案稀疏儲存,可以大幅降低index檔案元資料佔用空間大小。
參考