1. 程式人生 > >Kafka冷門知識——主題刪除背後的祕密

Kafka冷門知識——主題刪除背後的祕密

在本文開篇中先讓大家來思考一個問題,這個問題也是來源於一次真實的應用案例,案例內容的具體步驟如下:

  • step 1. 建立一個主題,假設主題名為topic-offset;
  • step 2. 建立生產者往這個主題中寫入若干訊息,然後關閉生產者;
  • step 3. 建立消費者消費這個主題中的訊息,並將消費位移存入__consumer_offsets這個主題中(假設這裡消費組的名稱groupId=“group.offset”),然後關閉消費者;
  • step 4. 刪除topic-offset這個主題;
  • step 5. 在step3中提交的消費位移過期時間內(Kafka中預設過期時間是1440mins,即1天)再次建立topic-offset主題,主題的所有屬性均和step 1中的相同;

至此,便可以引出了筆者的問題了:如果此時再建立一個消費者,並且這個消費者設定的消費組的名稱也為"group.offset",那麼這個消費者是從step 3中__consumer_offsets中儲存的位置開始消費還是根據消費者自身所設定的“auto.offset.reset”引數來決定開始消費的位置。
在這裡插入圖片描述

或許你對這個問題一臉懵逼,筆者先來簡單講一下消費位移的相關知識點:我們知道在舊版的消費者中會將消費位移儲存在Zookeeper節點中,顯然Zookeeper不適合多寫的應用場景。在新版的消費者中將消費位移儲存在了Kafka內部的主題__consumer_offsets中。每當消費者有消費位移提交時,會通過OffsetCommitRequest請求將所提交的位移傳送給消費者所屬消費組對應的組協調器GroupCoordinator中,組協調器GroupCoordinator會將消費位移存入到__consumer_offsets主題中,同時也會在記憶體中保留一份備份。Kafka重啟之後會將__consumer_offsets中所有的訊息儲存到記憶體中,即儲存到各個GroupCoordinator中來進行維護。

如此看起來__consumer_offsets中的消費位移不會丟失,也就是說在step 5之後再建立一個相同消費組下的消費者時是會獲取(OffsetFetchRequest)到之前提交的位移資訊的,事實是否真的如此,這裡先賣個關子,我們從主題的刪除過程來進行切入分析。

就以topic-offset為例,我們可以通過kafka-topics.sh指令碼、KafkaAdminClient等工具來刪除它,這波操作產生的最直接的結果就是在Kafka對應的Zoopeer中的/admin/delete_topics/路徑下建立一個以“topic-offset”命名的實節點。KafkaController會監聽/admin/delete_topics/路徑下的節點變化,當監聽到有節點變化時就會接過前面kafka-topics.sh指令碼、KafkaAdminClient等工具的交接棒,負責接下去的具體的刪除工作,對於刪除“topic-offset”而言,具體的工作有如下:

  1. 刪除Zookeeper中的/admin/delete_topics/topic-offset節點、/brokers/topics/topic-offset節點以及/config/topics/topic-offset節點,後兩個節點和主題的元資料資訊、配置資訊有關,所以也要刪除掉。
  2. 通知各個broker節點將主題“topic-offset”下的所有日誌檔案標記刪除,具體可以檢視Kafka日誌刪除那部分的細節。
  3. 通知各個broker節點中的GroupCoordinator以刪除有關此主題的消費位移資訊。
    前兩個大家都能猜想的出來,第3個大家未必有所瞭解。GroupCoordinator會遍歷旗下所有的消費組,然後刪除有關topic-offset的分割槽資訊,並且通過在__consumer_offsets中設定墓碑訊息來刪除對應的記錄。

下圖中__consumer_offsets主題中有關消費位移的訊息格式,圖中上半部分表示訊息的key,裡面包含version(版本資訊)、group(消費組的名稱)、topic(主題名稱,這裡就是topic-offset)以及partition(分割槽編號);圖中下半部分表示訊息的value,對於墓碑訊息來說,value設定為null,由於__consumer_offsets的清理策略是compact的,這個墓碑訊息最終會被清除掉。
在這裡插入圖片描述

分析到這裡,我們再來回顧文中開篇的問題,相信到這裡答案已經顯而易見了,刪除了主題之後會順帶著將主題相關的所有消費位移資訊全部刪除,故在step 5之後的新消費者無跡可尋,故只能按照其所配置的auto.offset.reset引數來做具體的earliest或者lateset的重置消費。

本文中涉及到的概念有GroupCoordinator、KafkaController、Kafka日誌刪除、Kafka協議、GroupMetadata、墓碑訊息等,如果你對此一無所知或者一知半解的話,那麼說明你對Kafka的認知接近為0,如何排解未知的恐慌?——掃描關注微信公眾號:朱小廝的部落格。


歡迎支援《RabbitMQ實戰指南》以及關注微信公眾號:朱小廝的部落格。