https://github.com/apache/kafka/pull/17367
背景故事
今天這個主題比較複雜一點,但小編我會盡量用廢文的方式來呈現。大家在用Admin
的時候會不會好奇背後到底用了多少請求?例如一個很常見的操作LIST_OFFSET
,其實背後涉及了兩個流程:
partition
的領導是哪個節點partition
的資訊第一步很重要因為它可以讓我們跟正確的節點索取資訊,因為只有partition leader
才會有即時最新最正確的資料。那麼到這裏就有一個問題可以討論了,在大規模使用中partitions
可能成千上萬,我們是否每次呼叫LIST_OFFSET
的時候,都必須先執行第一步去取得所有partition leader
呢?如果是的話,那這樣的開銷會不會很大?沒錯,事實上這的確是一個開銷,而這也是使用者所反應的情境,當面對大規模且穩定的叢集時,任何需要partition leader
的操作都會反覆的索取大量資訊,這對於一個長期使用的Admin
來說其實是一個不容忽視的資源浪費。事實上不只是LIST_OFFSET
,以下請求也都有類似的問題:
DELETE_RECORDS
DESCRIBE_PRODUCERS
ABORT_TRANSACTION
這些操作都有一個共同點,他們都需要知道partition leader
,對於DELETE_RECORDS
來說,刪除資料這件事情只能透過partition leader
。DESCRIBE_PRODUCERS
則是要從leader
身上才會知道現在有哪些正在寫入的producer
。ABORT_TRANSACTION
這個則是由於kafka
的交易行為其實是透過在各個相關的partition
寫入一些特殊的資料來判斷交易的範圍,因此自然也需要知道partition leader
是誰才能把中斷的請求送到正確的對象。
所以大家可以想想看,如果你今天用Admin
操作一個非常非常大的叢集,然後上述幾個請求你三五不時會發送一下,但每次大量的partition leader
查詢操作把你弄得很煩,那此時你會怎麼辦?
解決辦法
沒錯,你想的和大家想的都一樣,為什麼不把partition leader
的資訊快取起來呢?尤其各個partition
的領導是不太會更換,就算有也只是少數,因此如果有操作會需要索取partition leader
時,其實我們應該要嘗試把這些資訊快取下來,而不是每次對應的請求出現時都要重新拉取partition leader
,這樣一來可以節省很多寶貴的時間、二來也可以降低伺服器端的壓力。
等等,在操作Admin
的時候我們又不知道對面的叢集多大、也不知道是否穩定,如果快取一直失誤怎麼辦?其實這個到也不用擔心,因為Kafka
本來就有良好的retry
機制,也就是說當快取失誤導致我們發送請求給不正確的節點時,節點會回傳對應的錯誤訊息,例如leader
不存在,或是該partition
並不屬於它管轄,在這種情境下我們就可以知道可能是送錯對象了,此時就可以觸發更新快取的動作,換言之,就算快取失誤我們也不用更新所有資料,只要針對失誤的部分進行部分更新,如此就算在快取失誤的情境下我們依然可以避免不必要的請求,進而達到效能上的改善
廣告
歡迎訂閱全臺最鬆散的開源社群源來適你,上面不定期會有各種開源的廢文。也歡迎參加全臺最鬆散的開源討論頻道,上面有一群網友一起在刷開源技術