kafka存儲機制
@(博客文章)[storm|大數據]
大部分內容參考自:http://tech.meituan.com/kafka-fs-design-theory.html
基礎知識請參考:http://www.lujinhong.com/kafka%E9%9B%86%E7%BE%A4%E5%8E%9F%E7%90%86%E4%BB%8B%E7%BB%8D.html
關於kafka中的time stamp與offset的關系,請參考:
(一)關鍵術語
復習一下幾個基本概念,詳見上面的基礎知識文章。
Broker:消息中間件處理結點,一個Kafka節點就是一個broker,多個broker能夠組成一個Kafka集群。
Topic:一類消息,比如page view日志、click日志等都能夠以topic的形式存在。Kafka集群能夠同一時候負責多個topic的分發。
Partition:topic物理上的分組。一個topic能夠分為多個partition,每一個partition是一個有序的隊列。
Segment:partition物理上由多個segment組成。以下有具體說明。
offset:每一個partition都由一系列有序的、不可變的消息組成,這些消息被連續的追加到partition中。partition中的每一個消息都有一個連續的序列號叫做offset,用於partition中唯一標識的這條消息。
分析過程分為以下4個步驟:
topic中partition存儲分布
partiton中文件存儲方式
partiton中segment文件存儲結構
在partition中怎樣通過offset查找message
通過上述4過程具體分析,我們就能夠清楚認識到kafka文件存儲機制的奧秘。
(二)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集群partition分布原理分析
(三) partiton中文件存儲方式
以下示意圖形象說明了partition中文件存儲方式:
每一個partion(文件夾)相當於一個巨型文件被平均分配到多個大小相等segment(段)數據文件里。
但每一個段segment file消息數量不一定相等,這樣的特性方便old segment file高速被刪除。(默認情況下每一個文件大小為1G)
每一個partiton僅僅須要支持順序讀寫即可了。segment文件生命周期由服務端配置參數決定。
這樣做的優點就是能高速刪除無用文件。有效提高磁盤利用率。
(四) partiton中segment文件存儲結構
讀者從上節了解到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中一對segment file文件為例。說明segment中index<—->data file相應關系物理結構例如以下:
上述圖3中索引文件存儲大量元數據,數據文件存儲大量消息,索引文件里元數據指向相應數據文件里message的物理偏移地址。
當中以索引文件里元數據3,497為例,依次在數據文件里表示第3個message(在全局partiton表示第368772個message)、以及該消息的物理偏移地址為497。
從上述圖3了解到segment data file由很多message組成,以下具體說明message物理結構例如以下:
keyword 解釋說明
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 表示實際消息數據。
(五)在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設置一個元數據指針,它比稠密索引節省了很多其它的存儲空間,但查找起來須要消耗很多其它的時間。
(六)Kafka文件存儲機制–實際執行效果
實驗環境:
Kafka集群:由2台虛擬機組成
cpu:4核
物理內存:8GB
網卡:千兆網卡
jvm heap: 4GB
具體Kafka服務端配置及其優化請參考:kafka server.properties配置具體解釋
從上述圖5能夠看出,Kafka執行時非常少有大量讀磁盤的操作。主要是定期批量寫磁盤操作。因此操作磁盤非常高效。
這跟Kafka文件存儲中讀寫message的設計是息息相關的。Kafka中讀寫message有例如以下特點:
寫message
消息從java堆轉入page cache(即物理內存)。
由異步線程刷盤,消息從page cache刷入磁盤。
讀message
- 消息直接從page cache轉入socket發送出去。
- 當從page cache沒有找到相應數據時,此時會產生磁盤IO,從磁
盤Load消息到page cache,然后直接從socket發出去
(七) 總結
Kafka高效文件存儲設計特點
Kafka把topic中一個parition大文件分成多個小文件段。通過多個小文件段,就easy定期清除或刪除已經消費完文件。降低磁盤占用。
通過索引信息能夠高速定位message和確定response的最大大小。
通過index元數據所有映射到memory,能夠避免segment file的IO磁盤操作。
通過索引文件稀疏存儲,能夠大幅降低index文件元數據占用空間大小。