Kafka-持久化和索引機制

i沒有t 發佈 2020-07-03T05:06:03+00:00

持久化機制一個 Topic 被分成多 Partition,每個 Partition 在存儲層面是一個 append-only 日誌文件,屬於一個 Partition 的消息都會被直接追加到日誌文件的尾部,每條消息在文件中的位置稱為 offset(偏移量)。

持久化機制

一個 Topic 被分成多 Partition,每個 Partition 在存儲層面是一個 append-only 日誌文件,屬於一個 Partition 的消息都會被直接追加到日誌文件的尾部,每條消息在文件中的位置稱為 offset(偏移量)。

日誌文件由「日誌條目(log entries)」序列組成,每一個日誌條目包含一個4字節整型數(值為N),其後跟N個字節的消息體。每條消息都有一個當前 Partition 下唯一的64字節的 offset,標識這條消息的起始位置。消息格式如下:

On-disk format of a message

offset         : 8 bytes 
message length : 4 bytes (value: 4 + 1 + 1 + 8(if magic value > 0) + 4 + K + 4 + V)
crc            : 4 bytes
magic value    : 1 byte
attributes     : 1 byte
timestamp      : 8 bytes (Only exists when magic value is greater than zero)
key length     : 4 bytes
key            : K bytes
value length   : 4 bytes
value          : V bytes

Kafka 持久化日誌視圖

日誌文件允許串行附加,並且總是附加到最後一個文件。當文件達到配置指定的大小(log.segment.bytes = 1073741824 (bytes))時,就會被滾動到一個新文件中(每個文件稱為一個 segment file)。日誌有兩個配置參數:M,強制作業系統將文件刷新到磁碟之前寫入的消息數;S,強制作業系統將文件刷新到磁碟之前的時間(秒)。在系統崩潰的情況下,最多會丟失M條消息或S秒的數據。

通過給出消息的偏移量(offset)和最大塊大小(S)來讀取數據。返回一個緩衝區為S大小的消息疊代器,S應該大於任何單個消息的大小,如果消息異常大,則可以多次重試讀取,每次都將緩衝區大小加倍,直到成功讀取消息為止。可以指定最大消息大小和緩衝區大小,以使伺服器拒絕大於某個大小的消息。讀取緩衝區可能以部分消息結束,這很容易被大小分隔檢測到。

讀取指定偏移量的數據時,需要首先找到存儲數據的 segment file,由全局偏移量計算 segment file 中的偏移量,然後從此位置開始讀取。

刪除

消息數據隨著 segment file 一起被刪除。Log manager 允許可插拔的刪除策略來選擇哪些文件符合刪除條件。當前策略為刪除修改時間超過 N 天前的任何日誌,或者是保留最近的 N GB 的數據。

為了避免在刪除時阻塞讀操作,採用了 copy-on-write 技術:刪除操作進行時,讀取操作的二分查找功能實際是在一個靜態的快照副本上進行的。

索引機制

kafka解決查詢效率的手段之一是將數據文件分段存儲,可以配置每一個文件的大小。每一個端單獨放在一個.log的文件中,數據文件命名是20個字符的長度,以每一個分段文件開始的最下offset來命名,其他位置用0填充。最初始的文件是00000000000000000000.log命名的,比如下一個log中的第一條消息的offset是18987,則該log文件的命名是00000000000000018987.log

其中每一個log文件的大小默認是1GB,每生成一個log文件就會對應產生一個index文件,是和log文件的命名相同的。這樣在進行消息檢索的時候可以快速利用二分的方法進行查找,定位到某一個分段文件中。

數據文件的分段使得可以在一個較小的數據文件中找到對應的offset的message了。在index文件中的索引實際也是稀疏性的,並不是全部都建立索引的。(這也是考慮到index文件在加載到內存的時候,能不占用大量的內存和CPU資源)索引文件中包含的若干條目,每個條目表示的數據文件中的一條message的索引--以是當前的message在數據文件的offset和在文件的position(message在文件中的絕對位置信息)的對應關係。如下圖所示:

其中00000000000000000000.index文件中的34597對應到00000000000000000000.log文件中的第三條消息,並且該消息的絕對位置是4597。但是如果消費者想要 獲取57912的話,此時index文件中並沒有5,所以根據二分查找,先找到3的位置,在進行順序掃描從而找到57912的message。

index文件中並沒有為每一條message建立索引。而是採用了稀疏存儲的方式,每隔一定字節的數據建立一條索引,這樣的話就是避免了索引文件占用過多的空間和資源,從而可以將索引文件保留到內存中。缺點是沒有建立索引的數據在查詢的過程中需要小範圍內的順序掃描操作。

索引文件映射到內存的話,從而提高了查找的速度信息。

關鍵字: