Kafka科普系列 | 轻松理解Kafka中的延时操作
歡迎跳轉到本文的原文鏈接:https://honeypps.com/mq/kafka-basic-knowledge-of-delay-operation/
本文起源于之前去面試的一道面試題,面試題大致上是這樣的:消費者去Kafka里拉去消息,但是目前Kafka中又沒有新的消息可以提供,那么Kafka會如何處理?
如下圖所示,兩個follower副本都已經拉取到了leader副本的最新位置,此時又向leader副本發送拉取請求,而leader副本并沒有新的消息寫入,那么此時leader副本該如何處理呢?可以直接返回空的拉取結果給follower副本,不過在leader副本一直沒有新消息寫入的情況下,follower副本會一直發送拉取請求,并且總收到空的拉取結果,這樣徒耗資源,顯然不太合理。
這里就涉及到了Kafka延遲操作的概念。Kafka在處理拉取請求時,會先讀取一次日志文件,如果收集不到足夠多(fetchMinBytes,由參數fetch.min.bytes配置,默認值為1)的消息,那么就會創建一個延時拉取操作(DelayedFetch)以等待拉取到足夠數量的消息。當延時拉取操作執行時,會再讀取一次日志文件,然后將拉取結果返回給follower副本。
延遲操作不只是拉取消息時的特有操作,在Kafka中有多種延時操作,比如延時數據刪除、延時生產等。
對于延時生產(消息)而言,如果在使用生產者客戶端發送消息的時候將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。
那么這里等待消息3和消息4寫入follower1副本和follower2副本,并返回相應的響應結果給客戶端的動作是由誰來執行的呢?在將消息寫入leader副本的本地日志文件之后,Kafka會創建一個延時的生產操作(DelayedProduce),用來處理消息正常寫入所有副本或超時的情況,以返回相應的響應結果給客戶端。
延時操作需要延時返回響應的結果,首先它必須有一個超時時間(delayMs),如果在這個超時時間內沒有完成既定的任務,那么就需要強制完成以返回響應結果給客戶端。其次,延時操作不同于定時操作,定時操作是指在特定時間之后執行的操作,而延時操作可以在所設定的超時時間之前完成,所以延時操作能夠支持外部事件的觸發。
就延時生產操作而言,它的外部事件是所要寫入消息的某個分區的HW(高水位)發生增長。也就是說,隨著follower副本不斷地與leader副本進行消息同步,進而促使HW進一步增長,HW每增長一次都會檢測是否能夠完成此次延時生產操作,如果可以就執行以此返回響應結果給客戶端;如果在超時時間內始終無法完成,則強制執行。
回顧一下文中開頭的延時拉取操作,它也同樣如此,也是由超時觸發或外部事件觸發而被執行的。超時觸發很好理解,就是等到超時時間之后觸發第二次讀取日志文件的操作。外部事件觸發就稍復雜了一些,因為拉取請求不單單由follower副本發起,也可以由消費者客戶端發起,兩種情況所對應的外部事件也是不同的。如果是follower副本的延時拉取,它的外部事件就是消息追加到了leader副本的本地日志文件中;如果是消費者客戶端的延時拉取,它的外部事件可以簡單地理解為HW的增長。
延遲操作背后還有一些更深層次的內容,比如對于“煉獄”、“收割機”的理解,嘿嘿~~這些內容都在《深入理解Kafka》中
歡迎跳轉到本文的原文鏈接:https://honeypps.com/mq/kafka-basic-knowledge-of-delay-operation/
歡迎支持筆者新作:《深入理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公眾號:朱小廝的博客。
總結
以上是生活随笔為你收集整理的Kafka科普系列 | 轻松理解Kafka中的延时操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kafka科普系列 | 什么是LSO?
- 下一篇: Kafka科普系列 | 原来Kafka