Kafka中的索引機(jī)制

在kafka中,每個(gè)日志分段文件都對(duì)應(yīng)了兩個(gè)索引文件——偏移量索引文件和時(shí)間戳索引文件(還有其它的諸如事務(wù)日志索引文件就不細(xì)表了),主要用來提高查找消息的效率。

  • 偏移量索引文件用來建立消息偏移量(offset)到物理地址之間的映射關(guān)系,方便快速定位消息所在的物理文件位置;
  • 時(shí)間戳索引文件則根據(jù)指定的時(shí)間戳(timestamp)來查找對(duì)應(yīng)的偏移量信息

偏移量索引文件用來建立消息偏移量(offset)到物理地址之間的映射關(guān)系,方便快速定位消息所在的物理文件位置;時(shí)間戳索引文件則根據(jù)指定的時(shí)間戳(timestamp)來查找對(duì)應(yīng)的偏移量信息。

Kafka 中的索引文件以稀疏索引(sparse index)的方式構(gòu)造消息的索引,它并不保證每個(gè)消息在索引文件中都有對(duì)應(yīng)的索引項(xiàng)。

每當(dāng)寫入一定量 (由 broker 端參數(shù) log.index.interval.bytes 指定,默認(rèn)值為 4096,即 4KB) 的消息時(shí),偏移量索引文件和時(shí)間戳索引文件分別增加一個(gè)偏移量索引項(xiàng)和時(shí)間戳索引項(xiàng),增大或減小 log.index.interval.bytes 的值,對(duì)應(yīng)地可以縮小或增加索引項(xiàng)的密度。

稀疏索引通過 MappedByteBuffer 將索引文件映射到內(nèi)存中,以加快索引的查詢速度。

偏移量索引文件中的偏移量是單調(diào)遞增的,查詢指定偏移量時(shí),使用二分查找法來快速定位偏移量的位置,如果指定的偏移量不在索引文件中,則會(huì)返回小于指定偏移量的最大偏移量。

時(shí)間戳索引文件中的時(shí)間戳也保持嚴(yán)格的單調(diào)遞增,查詢指定時(shí)間戳?xí)r,也根據(jù)二分查找法來查找不大于該時(shí)間戳的最大偏移量,至于要找到對(duì)應(yīng)的物理文件位置還需要根據(jù)偏移量索引文件來進(jìn)行再次定位。

稀疏索引的方式是在磁盤空間、內(nèi)存空間、查找時(shí)間等多方面之間的一個(gè)折中。

以偏移量索引文件來做具體分析。偏移量索引項(xiàng)的格式如下圖所示。

每個(gè)索引項(xiàng)占用 8 個(gè)字節(jié),分為兩個(gè)部分:

(1) relativeOffset: 相對(duì)偏移量,表示消息相對(duì)于 baseOffset 的偏移量,占用 4 個(gè)字節(jié),當(dāng)前索引文件的文件名即為 baseOffset 的值。

(2) position: 物理地址,也就是消息在日志分段文件中對(duì)應(yīng)的物理位置,占用 4 個(gè)字節(jié)。

image

消息的偏移量(offset)占用 8 個(gè)字節(jié),也可以稱為絕對(duì)偏移量。

索引項(xiàng)中沒有直接使用絕對(duì)偏移量而改為只占用 4 個(gè)字節(jié)的相對(duì)偏移量(relativeOffset = offset - baseOffset),這樣可以減小索引文件占用的空間。

舉個(gè)例子,一個(gè)日志分段的 baseOffset 為 32,那么其文件名就是 00000000000000000032.log,offset 為 35 的消息在索引文件中的 relativeOffset 的值為 35-32=3。

image

如果我們要查找偏移量為 23 的消息,那么應(yīng)該怎么做呢?首先通過二分法在偏移量索引文件中找到不大于 23 的最大索引項(xiàng),即[22, 656],然后從日志分段文件中的物理位置 656 開始順序查找偏移量為 23 的消息。

image

以上是最簡單的一種情況。參考上圖,如果要查找偏移量為 268 的消息,那么應(yīng)該怎么辦呢?

首先肯定是定位到baseOffset為251的日志分段,然后計(jì)算相對(duì)偏移量relativeOffset = 268 - 251 = 17,之后再在對(duì)應(yīng)的索引文件中找到不大于 17 的索引項(xiàng),最后根據(jù)索引項(xiàng)中的 position 定位到具體的日志分段文件位置開始查找目標(biāo)消息。

那么又是如何查找 baseOffset 為 251 的日志分段的呢?

這里并不是順序查找,而是用了跳躍表的結(jié)構(gòu)。

Kafka 的每個(gè)日志對(duì)象中使用了 ConcurrentSkipListMap 來保存各個(gè)日志分段,每個(gè)日志分段的 baseOffset 作為 key,這樣可以根據(jù)指定偏移量來快速定位到消息所在的日志分段。

在Kafka中要定位一條消息,那么首先根據(jù) offset 從 ConcurrentSkipListMap 中來查找到到對(duì)應(yīng)(baseOffset)日志分段的索引文件,然后讀取偏移量索引索引文件,之后使用二分法在偏移量索引文件中找到不大于 offset - baseOffset z的最大索引項(xiàng),接著再讀取日志分段文件并且從日志分段文件中順序查找relativeOffset對(duì)應(yīng)的消息。

Kafka中通過offset查詢消息內(nèi)容的整個(gè)流程我們可以簡化成下圖:


image

Kafka和MySQL的索引區(qū)別

1、Kafka中的offset類比成InnoDB中的主鍵

Kafka中消息的offset可以類比成InnoDB中的主鍵,前者是通過offset檢索出整條Record的數(shù)據(jù),后者是通過主鍵檢索出整條Record的數(shù)據(jù)。

InnoDB中通過主鍵查詢數(shù)據(jù)內(nèi)容的整個(gè)流程建議簡化成下圖(下半部分)。

image

Kafka中通過時(shí)間戳索引文件去檢索消息的方式可以類比于InnoDB中的輔助索引的檢索方式:

前者是通過timestamp去找offset,后者是通過索引去找主鍵,后面兩者的過程就和上面的陳述相同。

Kafka中當(dāng)有新的索引文件建立的時(shí)候ConcurrentSkipListMap才會(huì)更新,而不是每次有數(shù)據(jù)寫入時(shí)就會(huì)更新,這塊的維護(hù)量基本可以忽略

B+樹中數(shù)據(jù)有插入、更新、刪除的時(shí)候都需要更新索引,還會(huì)引來“頁分裂”等相對(duì)耗時(shí)的操作。Kafka中的索引文件也是順序追加文件的操作,和B+樹比起來工作量要小很多。

2、應(yīng)用場景不同所決定

說到底還是應(yīng)用場景不同所決定的。MySQL中需要頻繁地執(zhí)行CRUD的操作,CRUD是MySQL的主要工作內(nèi)容,而為了支撐這個(gè)操作需要使用維護(hù)量大很多的B+樹去支撐。

Kafka中的消息一般都是順序?qū)懭氪疟P,再到從磁盤順序讀出(不深入探討page cache等),他的主要工作內(nèi)容就是:寫入+讀取,很少有檢索查詢的操作

換句話說,檢索查詢只是Kafka的一個(gè)輔助功能,不需要為了這個(gè)功能而去花費(fèi)特別太的代價(jià)去維護(hù)一個(gè)高level的索引。

前面也說過,Kafka中的這種方式是在磁盤空間、內(nèi)存空間、查找時(shí)間等多方面之間的一個(gè)折中。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • kafka生產(chǎn)者生產(chǎn)的消息需要存儲(chǔ)在服務(wù)端,那么服務(wù)端就需要保證消息的健壯性,需要保證其線性擴(kuò)展,負(fù)載均衡,故障容...
    紹圣閱讀 531評(píng)論 0 0
  • 摘要:消息存儲(chǔ)對(duì)于每一款消息隊(duì)列都非常重要,那么Kafka在這方面是如何來設(shè)計(jì)做到高效的呢?Kafka這款分布式消...
    癲狂俠閱讀 29,465評(píng)論 4 45
  • 在進(jìn)行詳解之前,我想先聲明一下,本次我們進(jìn)行講解說明的是 Kafka 消息存儲(chǔ)的信息文件內(nèi)容,不是所謂的 Kafk...
    程序員日常填坑閱讀 3,603評(píng)論 0 1
  • 1.消息的保存路徑 消息發(fā)送端發(fā)送消息到 broker 上以后,消息是如何持久化的呢?那么接下來去分析下消息的存儲(chǔ)...
    Mrsunup閱讀 567評(píng)論 0 1
  • 你從七月來閱讀 330評(píng)論 0 0

友情鏈接更多精彩內(nèi)容