Kafka知識盤點【貳】_broker

Kafka知識盤點【壹】_生產者

 

kafka broker這部分,可能是kafka系列知識的核心所在。好好總結。

 

1.消息的存儲

1.1 存儲文件

在上文曾經介紹過,kafka的消息都是由partition爲維度保存的。實際情況下,每個partition正是broker上的一個文件夾,文件夾下保存了segment和index兩種文件。

segment文件分爲日誌文件和索引文件。日誌文件後綴名爲.log,保存在/${topicName}-${partitionid}/路徑下,是實際保存消息的日誌文件。每個文件最大不超過1G,超過後將新建文件繼續保存。文件名命名規則是64位long大小,19位數字字符長度,不足用0填充,數字是上一個log文件的最後一個offset值+1。

索引文件保存路徑與.log文件一致。索引文件的分段邏輯默認和log文件一樣,同時也支持單獨配置。索引不會針對每條消息都創建,而是當log文件每隔一定的字節數(由log.index.interval.bytes配置,默認4KB)再創建。索引文件可分爲偏移量索引(offset index)和時間戳索引(timestamp index)兩種。

偏移量索引:後綴名爲.index。每條索引佔8個字節,包含relativeOffset和position兩部分。relativeOffset是相對偏移量佔用4個字節,表示消息相對於日誌分段文件名的偏移量(relativeOffset = 消息偏移量messageOffset - 消息所在日誌分段文件的開始偏移量baseOffset)。position是消息所在具體的日誌分段文件的位置,佔用4個字節,。

時間戳索引:後綴名爲.timeindex。每條索引佔12個字節,包含timestamp(8字節)和relativeOffset兩部分。timestamp是當前日誌分段文件最大時間戳,遞增保存;relativeOffset是時間戳對應的消息先對偏移量。查找思路就是先根據消息時間戳對應的時間戳索引文件找到相對偏移量,再到上面相應的偏移量索引文件中查找。

1.2存儲方式

大家都說kafka的性能高除了以上合理的消息存儲設計,還有使用了頁緩存及零拷貝技術。頁緩存即pagecache,操作系統會先查看待讀取的數據以頁爲單位加載到頁緩存中。後續進程讀取數據時,會先判斷頁緩存中是否存在,如存在則直接獲取返回,而不用再去讀取磁盤。這裏只做簡單介紹,下面我們說一下零拷貝。

首先說,linux系統傳統的數據拷貝是如何完成的:

可以看到在linux系統的用戶態和內核態中間的數據拷貝需要cpu來完成,產生性能消耗。爲了優化這個問題,linux提供了零拷貝技術。這裏需要注意的是,零拷貝指的是沒有用戶態和內核態直接的數據拷貝。

kafka採用的是調用sendFile()方式,數據通過DMA讀取到內核緩衝區。內核緩衝區中的數據通過DMA聚合網絡緩衝區,然後一齊發送到網卡。

擴展一下rocketMQ也應用了零拷貝技術,不過使用的是Mmap方式。mmap先在內存申請一塊區域,然後把文件映射到虛擬內存,從而省去了從read buffer複製到用戶緩存的步驟,減少了一次cpu拷貝。rocketMQ還做了空間預分配和數據預熱來優化性能。

 

2.高可用機制

2.1 副本replica

replica(上圖中綠色節點)可理解爲消息分區日誌(紅色節點)的副本,由於kafka broker一般以集羣方式部署,因此分區日誌的副本一般會創建在其他broker上。和其他分佈式中間件的設計一樣,副本也分爲leader和follower兩種角色。但是kafka對消息都是主寫主讀。

默認情況下,所有的分區的副本都處於ISR(in-sync replica)集合中,通過zk來維護。當kafka生產者發送消息的配置acks是all時,只有當ISR中所有replica都收到消息,消息才認爲發送成功。如果某replica滯後同步一定程度(replica.lag.time.max.ms),則將其踢出ISR集合,當其追上後再將其加入。

當leader掛掉後,kafka從ISR集合中的follower選出一個作爲新的leader,這個選舉操作由controller完成。選取的思路就是,先獲取所有副本的集合,按副本id升序獲取第一個同時也在ISR集合中的副本,作爲新的leader。

那麼controller是什麼角色呢?

 

2.2 Controller

其實就是broker集羣中的一臺,會負責管理整個集羣素有分區和副本的狀態。和ISR一樣,controller也是通過zk來維護,競選成功的broker會在zk中創建/controller臨時節點,記錄自己的brokerId和version。每個broker啓動的時候都會嘗試去競選controller,當獲取/controller臨時節點的brokerId發現不是-1時,說明controller已經存在,則不再競選,並把broker保存到內存中。

/controller臨時節點中的version,是通過zk另一個/controller_epoch持久節點維護,用於記錄controller發生變更的次數,記錄這是第幾代controller。kafka正是通過這個值來保證controller的唯一性(kafka的leader選舉也有類似設計)。

說白了,controller的競選,就是爭取創建zk的/controller臨時節點。

 

下一篇:Kafka知識盤點【叄】_消費者

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章