kafka的目錄結構和RocketMQ -- 訊息傳送儲存流程是不一樣的,但是某部分思想還是一致的。
首先是kafka-logs下,放的是topic+partition的資料夾,比如topic為test的有2個partition(假設都在這個Broker上),那就有兩個檔案,分別為test-0,test-1。
每個檔案下,都有很多log檔案以及對應的兩個索引檔案。每個log檔案又叫segment。
segment檔案的大小也是1G,每個檔名是訊息的物理偏移量。
當broker接收到訊息的時候,首先會進行一些判斷,比如許可權驗證、acks的引數是否合法。
等驗證通過後,遍歷訊息裡的每個分割槽處理資料。比如test對應的分割槽0,根據上面的目錄結構圖,就知道會找到test-0的副本里。
找到後,就會申請讀鎖,並獲取leader的partition,因為只有leader才可以寫資料。
上面加的是讀鎖,等寫入segment檔案的時候,還要再加一次鎖。
申請到鎖後,開始選擇segment檔案,如果是剛開始寫入日誌檔案的時候,此時並沒有segment檔案,所以就會建立一個大小為1G名字為00000000000000000000的日誌檔案。如果已經存在多個日誌檔案,那直接取最後一個日誌檔案,因為日誌檔案寫完才會建立一個新的日誌檔案,那最後一個日誌檔案就是當前需要寫入的。
如果這個寫入的訊息大小和當前選擇的segment檔案大小加起來超過1G,那又會建立一個新的segment檔案。
如果segment對應的index或者timeIndex滿了,那也會建立一個新的segment檔案。
獲取到segment檔案後,就把訊息寫入記憶體中。
每寫4096位元組的訊息,就開始寫兩個索引檔案,當然寫入的時候,還是要先加鎖。
所以我們的索引檔案,並不是連續的。
寫完記憶體後,就會判斷是否需要刷盤,預設是不刷盤的,把刷盤操作交給作業系統定期的執行,所以會有資料丟失的情況。