Kafka科普系列 | 輕鬆理解Kafka中的延時操做

本文起源於以前去面試的一道面試題,面試題大體上是這樣的:消費者去Kafka里拉去消息,可是目前Kafka中又沒有新的消息能夠提供,那麼Kafka會如何處理?html

以下圖所示,兩個follower副本都已經拉取到了leader副本的最新位置,此時又向leader副本發送拉取請求,而leader副本並無新的消息寫入,那麼此時leader副本該如何處理呢?能夠直接返回空的拉取結果給follower副本,不過在leader副本一直沒有新消息寫入的狀況下,follower副本會一直髮送拉取請求,而且總收到空的拉取結果,這樣徒耗資源,顯然不太合理。 面試

在這裏插入圖片描述

這裏就涉及到了Kafka延遲操做的概念。Kafka在處理拉取請求時,會先讀取一第二天志文件,若是收集不到足夠多(fetchMinBytes,由參數fetch.min.bytes配置,默認值爲1)的消息,那麼就會建立一個延時拉取操做(DelayedFetch)以等待拉取到足夠數量的消息。當延時拉取操做執行時,會再讀取一第二天志文件,而後將拉取結果返回給follower副本。微信

延遲操做不僅是拉取消息時的特有操做,在Kafka中有多種延時操做,好比延時數據刪除、延時生產等。fetch

對於延時生產(消息)而言,若是在使用生產者客戶端發送消息的時候將acks參數設置爲-1,那麼就意味着須要等待ISR集合中的全部副本都確認收到消息以後才能正確地收到響應的結果,或者捕獲超時異常。 設計

在這裏插入圖片描述
假設某個分區有3個副本:leader、follower1和follower2,它們都在分區的ISR集合中。爲了簡化說明,這裏咱們不考慮ISR集合伸縮的狀況。Kafka在收到客戶端的生產請求後,將消息3和消息4寫入leader副本的本地日誌文件,如上圖所示。

因爲客戶端設置了acks爲-1,那麼須要等到follower1和follower2兩個副本都收到消息3和消息4後才能告知客戶端正確地接收了所發送的消息。若是在必定的時間內,follower1副本或follower2副本沒可以徹底拉取到消息3和消息4,那麼就須要返回超時異常給客戶端。生產請求的超時時間由參數request.timeout.ms配置,默認值爲30000,即30s。 3d

在這裏插入圖片描述
在這裏插入圖片描述

那麼這裏等待消息3和消息4寫入follower1副本和follower2副本,並返回相應的響應結果給客戶端的動做是由誰來執行的呢?在將消息寫入leader副本的本地日誌文件以後,Kafka會建立一個延時的生產操做(DelayedProduce),用來處理消息正常寫入全部副本或超時的狀況,以返回相應的響應結果給客戶端。日誌

延時操做須要延時返回響應的結果,首先它必須有一個超時時間(delayMs),若是在這個超時時間內沒有完成既定的任務,那麼就須要強制完成以返回響應結果給客戶端。其次,延時操做不一樣於定時操做,定時操做是指在特定時間以後執行的操做,而延時操做能夠在所設定的超時時間以前完成,因此延時操做可以支持外部事件的觸發。cdn

就延時生產操做而言,它的外部事件是所要寫入消息的某個分區的HW(高水位)發生增加。也就是說,隨着follower副本不斷地與leader副本進行消息同步,進而促使HW進一步增加,HW每增加一次都會檢測是否可以完成這次延時生產操做,若是能夠就執行以此返回響應結果給客戶端;若是在超時時間內始終沒法完成,則強制執行。htm

回顧一下文中開頭的延時拉取操做,它也一樣如此,也是由超時觸發或外部事件觸發而被執行的。超時觸發很好理解,就是等到超時時間以後觸發第二次讀取日誌文件的操做。外部事件觸發就稍複雜了一些,由於拉取請求不僅僅由follower副本發起,也能夠由消費者客戶端發起,兩種狀況所對應的外部事件也是不一樣的。若是是follower副本的延時拉取,它的外部事件就是消息追加到了leader副本的本地日誌文件中;若是是消費者客戶端的延時拉取,它的外部事件能夠簡單地理解爲HW的增加。blog

延遲操做背後還有一些更深層次的內容,好比對於「煉獄」、「收割機」的理解,嘿嘿~~這些內容都在《深刻理解Kafka》中


歡迎支持筆者小冊:《圖解Kafka之實戰指南》和《圖解Kafka之核心原理


歡迎支持筆者新做:《深刻理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公衆號:朱小廝的博客。

相關文章
相關標籤/搜索