Kafka檔案的儲存機制

2021-07-27 17:46:55 字數 3594 閱讀 8449

同乙個topic下有多個不同的partition,每個partition為乙個目錄,partition命名的規則是topic的名稱加上乙個序號,序號從0開始。

每乙個partition目錄下的檔案被平均切割成大小相等(預設乙個檔案是500兆,可以手動去設定)的資料檔案,

每乙個資料檔案都被稱為乙個段(segment file),但每個段訊息數量不一定相等,這種特性能夠使得老的segment可以被快速清除。

預設保留7天的資料。

每個partition下都會有這些每500兆乙個每500兆乙個(當然在上面的測試中我們將它設定為了1g乙個)的segment段。

另外每個partition只需要支援順序讀寫就可以了,partition中的每乙個segment端的生命週期是由我們在配置檔案中指定的乙個引數覺得的。

比如它在預設情況下,每滿500兆就會建立新的segment段(segment file),每滿7天就會清理之前的資料。

它的乙個特點就是支援順序寫。如下圖所示:

首先00000000000000000000.log檔案是最早產生的檔案,該檔案達到1g(因為我們在配置檔案裡面指定的1g大小,預設情況下是500兆)

之後又產生了新的0000000000000672348.log檔案,新的資料會往這個新的檔案裡面寫,這個檔案達到1g之後,資料就會再往下乙個檔案裡面寫,

也就是說它只會往檔案的末尾追加資料,這就是順序寫的過程,生產者只會對每乙個partition做資料的追加(寫)的操作。

問題:如何保證訊息消費的有序性呢?比如說生產者生產了0到100個商品,那麼消費者在消費的時候安裝0到100這個從小到大的順序消費,

那麼kafka如何保證這種有序性呢?難度就在於,生產者生產出0到100這100條資料之後,通過一定的分組策略儲存到broker的partition中的時候,

比如0到10這10條訊息被存到了這個partition中,10到20這10條訊息被存到了那個partition中,這樣的話,訊息在分組存到partition中的時候就已經被分組策略搞得無序了。

那麼能否做到消費者在消費訊息的時候全域性有序呢?遇到這個問題,我們可以回答,在大多數情況下是做不到全域性有序的。但在某些情況下是可以做到的。

比如我的partition只有乙個,這種情況下是可以全域性有序的。那麼可能有人又要問了,只有乙個partition的話,**來的分布式呢?**來的負載均衡呢?

所以說,全域性有序是乙個偽命題!全域性有序根本沒有辦法在kafka要實現的大資料的場景來做到。但是我們只能保證當前這個partition內部訊息消費的有序性。

結論:乙個partition中的資料是有序的嗎?回答:間隔有序,不連續。

針對乙個topic裡面的資料,只能做到partition內部有序,不能做到全域性有序。特別是加入消費者的場景後,如何保證消費者的消費的訊息的全域性有序性,

這是乙個偽命題,只有在一種情況下才能保證消費的訊息的全域性有序性,那就是只有乙個partition!。

segment file是什麼?

生產者生產的訊息按照一定的分組策略被傳送到broker中partition中的時候,這些訊息如果在記憶體中放不下了,就會放在檔案中,

partition在磁碟上就是乙個目錄,該目錄名是topic的名稱加上乙個序號,在這個partition目錄下,有兩類檔案,一類是以log為字尾的檔案,

一類是以index為字尾的檔案,每乙個log檔案和乙個index檔案相對應,這一對檔案就是乙個segment file,也就是乙個段。

其中的log檔案就是資料檔案,裡面存放的就是訊息,而index檔案是索引檔案,索引檔案記錄了元資料資訊。

說到segment file的索引檔案和資料檔案的一一對應,我們應該能想到storm中的ack file機制,在spout發出去的時候要發乙個ack tuple,

在下游的bolt處理完之後,它也要發乙個ack tuple,這兩個ack tuple裡面包含了同樣乙份資料,這個資料叫做messageid,它是乙個物件,

這個物件裡面包含兩個比較重要的字段,乙個是rootid,另乙個是tupleid(也叫錨點id),這個錨點id會在我們傳送資料的時候進行異或一下,

異或的結果才會傳送給ack那個bolt。

segment檔案命名的規則:partition全域性的第乙個segment從0(20個0)開始,後續的每乙個segment檔名是上乙個segment檔案中最後一條訊息的offset值。

那麼這樣命令有什麼好處呢?假如我們有乙個消費者已經消費到了368776(offset值為368776),那麼現在我們要繼續消費的話,怎麼做呢?

看上圖,分2個步驟,第1步是從所有檔案log檔案的的檔名中找到對應的log檔案,第368776條資料位於上圖中的「00000000000000368769.log」這個檔案中,

這一步涉及到乙個常用的演算法叫做「二分查詢法」(假如我現在給你乙個offset值讓你去找,你首先是將所有的log的檔名進行排序,然後通過二分查詢法進行查詢,

很快就能定位到某乙個檔案,緊接著拿著這個offset值到其索引檔案中找這條資料究竟存在**);第2步是到index檔案中去找第368776條資料所在的位置。

索引檔案(index檔案)中儲存這大量的元資料,而資料檔案(log檔案)中儲存這大量的訊息。

索引檔案(index檔案)中的元資料指向對應的資料檔案(log檔案)中訊息的物理偏移位址。

上圖的左半部分是索引檔案,裡面儲存的是一對一對的key-value,其中key是訊息在資料檔案(對應的log檔案)中的編號,比如「1,3,6,8……」,

分別表示在log檔案中的第1條訊息、第3條訊息、第6條訊息、第8條訊息……,那麼為什麼在index檔案中這些編號不是連續的呢?

這是因為index檔案中並沒有為資料檔案中的每條訊息都建立索引,而是採用了稀疏儲存的方式,每隔一定位元組的資料建立一條索引。

這樣避免了索引檔案占用過多的空間,從而可以將索引檔案保留在記憶體中。

但缺點是沒有建立索引的message也不能一次定位到其在資料檔案的位置,從而需要做一次順序掃瞄,但是這次順序掃瞄的範圍就很小了。

其中以索引檔案中元資料3,497為例,其中3代表在右邊log資料檔案中從上到下第3個訊息(在全域性partiton表示第368772個訊息),

其中497表示該訊息的物理偏移位址(位置)為497。

Kafka檔案的儲存機制

同乙個topic下有多個不同的partition,每個partition為乙個目錄,partition命名的規則是topic的名稱加上乙個序號,序號從0開始。每乙個partition目錄下的檔案被平均切割成大小相等 預設乙個檔案是500兆,可以手動去設定 的資料檔案,每乙個資料檔案都被稱為乙個段 s...

Kafka檔案的儲存機制

同乙個topic下有多個不同的partition,每個partition為乙個目錄,partition命名的規則是topic的名稱加上乙個序號,序號從0開始。每乙個partition目錄下的檔案被平均切割成大小相等 預設乙個檔案是500兆,可以手動去設定 的資料檔案,每乙個資料檔案都被稱為乙個段 s...

小記 kafka檔案儲存機制

topic是邏輯上的概念,partition是物理上的概念 kafka partition位置 var local kafka data kafka訊息預設儲存時間為7天 0000000000.log檔案預設值最大為1g,超過1g 會產生乙個新的檔案 由於生產者生產的訊息會不斷追加到log檔案末尾,...