kafka架構與原理

1、簡介

它可以讓你發佈和訂閱記錄流。在這方面,它類似於一個消息隊列或企業消息系統。

它可以讓你持久化收到的記錄流,從而具有容錯能力。

首先,明確幾個概念:

• Kafka運行在一個或多個服務器上。
• Kafka集羣分類存儲的記錄流被稱爲主題(Topics)。
• 每個消息記錄包含一個鍵,一個值和時間戳。

Kafka有四個核心API:

• 生產者 API 允許應用程序發佈記錄流至一個或多個Kafka的話題(Topics)。

• 消費者API 允許應用程序訂閱一個或多個主題,並處理這些主題接收到的記錄流。

• Streams API 允許應用程序充當流處理器(stream processor),從一個或多個主題獲取輸入流,並生產一個輸出流至一個或多個的主題,能夠有效地變換輸入流爲輸出流。

• Connector API 允許構建和運行可重用的生產者或消費者,能夠把 Kafka主題連接到現有的應用程序或數據系統。例如,一個連接到關係數據庫的連接器(connector)可能會獲取每個表的變化。

• Kafka的客戶端和服務器之間的通信是靠一個簡單的,高性能的,與語言無關的TCP協議完成的。這個協議有不同的版本,並保持向前兼容舊版本。Kafka不光提供了一個Java客戶端,還有許多語言版本的客戶端。

2、 架構

2.1 Broker

每個kafka server稱爲一個Broker,多個borker組成kafka cluster。一個機器上可以部署一個或者多個Broker,這多個Broker連接到相同的ZooKeeper就組成了Kafka集羣。

 

 

2.2 主題Topic

讓我們先來了解Kafka的核心抽象概念記錄流 – 主題。主題是一種分類或發佈的一系列記錄的名義上的名字。Kafka的主題始終是支持多用戶訂閱的; 也就是說,一個主題可以有零個,一個或多個消費者訂閱寫入的數據。

Topic 與broker

一個Broker上可以創建一個或者多個Topic。同一個topic可以在同一集羣下的多個Broker中分佈。

 

 

當然,Topic只是一個名義上的組件,真正在Broker間分佈式的Partition。

2.3 分區與日誌

一個主題對應多個分區,一個分區對應一個日誌

Kafka會爲每個topic維護了多個分區(partition),每個分區會映射到一個邏輯的日誌(log)文件。每個分區是一個有序的,不可變的消息序列,新的消息不斷追加到這個有組織的有保證的日誌上。分區會給每個消息記錄分配一個順序ID號 – 偏移量, 能夠唯一地標識該分區中的每個記錄。

日誌分區是分佈式的存在於一個kafka集羣的多個broker上。每個partition會被複制多份存在於不同的broker上。這樣做是爲了容災。具體會複製幾份,會複製到哪些broker上,都是可以配置的。經過相關的複製策略後,每個topic在每個broker上會駐留一到多個partition:

 

 

2.4 保留策略與Offset

Kafka集羣保留所有發佈的記錄,不管這個記錄有沒有被消費過,Kafka提供可配置的保留策略去刪除舊數據(還有一種策略根據分區大小刪除數據)。例如,如果將保留策略設置爲兩天,在記錄公佈後兩天內,它可用於消費,之後它將被丟棄以騰出空間。Kafka的性能跟存儲的數據量的大小無關, 所以將數據存儲很長一段時間是沒有問題的。

 

 

事實上,保留在每個消費者元數據中的最基礎的數據就是消費者正在處理的當前記錄的偏移量(offset)或位置(position)。這種偏移是由消費者控制:通常偏移會隨着消費者讀取記錄線性前進,但事實上,因爲其位置是由消費者進行控制,消費者可以在任何它喜歡的位置讀取記錄。例如,消費者可以恢復到舊的偏移量對過去的數據再加工或者直接跳到最新的記錄,並消費從“現在”開始的新的記錄。

這些功能的結合意味着,實現Kafka的消費者的代價都是很小的,他們可以增加或者減少而不會對集羣或其他消費者有太大影響。例如,你可以使用我們的命令行工具去追隨任何主題,而且不會改變任何現有的消費者消費的記錄。

2.5 Leader與Followers

一個Topic可能有很多分區,以便它能夠支持海量的的數據,更重要的意義是分區是進行並行處理的基礎單元。日誌的分區會跨服務器的分佈在Kafka集羣中,每個分區可以配置一定數量的副本分區提供容錯能力。爲了保證較高的處理效率,消息的讀寫都是在固定的一個副本上完成。這個副本就是所謂的Leader,而其他副本則是Follower,而Follower則會定期地到Leader上同步數據。

(1)leader處理所有的讀取和寫入分區的請求,而followers被動的從領導者拷貝數據。
(2)如果leader失敗了,followers之一將自動成爲新的領導者。
(3)每個服務器可能充當一些分區的leader和其他分區的follower,這樣的負載就會在集羣內很好的均衡分配。
(4)一個分區在同一時刻只能有一個消費者實例進行消費。

舉例:

 

 

可以看見我們一共有3個分區分別是0,1,2, replica 有2個:

partition 0 的leader在broker1, follower在broker2
partition 1 的leader在broker2, follower在broker0
partition 2 的leader在broker0, follower在brokder1

一個broker中不會出現兩個一樣的Partition,replica會被均勻的分佈在各個kafka server(broker)上 。Kafka並不允許replicas 數設置大於 broker數,因爲在一個broker上如果有2個replica其實是沒有意義的,因爲再多的replica同時在一臺broker上,隨着該broker的crash,一起不可用。

(1)Leader選舉與ISR

如果某個分區所在的服務器除了問題,不可用,kafka會從該分區的其他的副本中選擇一個作爲新的Leader。之後所有的讀寫就會轉移到這個新的Leader上。現在的問題是應當選擇哪個作爲新的Leader。顯然,只有那些跟Leader保持同步的Follower才應該被選作新的Leader。

Kafka會在Zookeeper上針對每個Topic維護一個稱爲ISR(in-sync replica,已同步的副本)的集合,該集合中是一些分區的副本。只有當這些副本都跟Leader中的副本同步了之後,kafka纔會認爲消息已提交,並反饋給消息的生產者。如果這個集合有增減,kafka會更新zookeeper上的記錄。如果某個分區的Leader不可用,Kafka就會從ISR集合中選擇一個副本作爲新的Leader。顯然通過ISR,kafka需要的冗餘度較低,可以容忍的失敗數比較高。假設某個topic有f+1個副本,kafka可以容忍f個服務器不可用。

(2)爲什麼不用少數服從多數的方法

少數服從多數是一種比較常見的一致性算法和Leader選舉法。它的含義是隻有超過半數的副本同步了,系統纔會認爲數據已同步;選擇Leader時也是從超過半數的同步的副本中選擇。這種算法需要較高的冗餘度。譬如只允許一臺機器失敗,需要有三個副本;而如果只容忍兩臺機器失敗,則需要五個副本。而kafka的ISR集合方法,分別只需要兩個和三個副本。

(3)如果所有的ISR副本都失敗了怎麼辦

此時有兩種方法可選,一種是等待ISR集合中的副本復活,一種是選擇任何一個立即可用的副本,而這個副本不一定是在ISR集合中。這兩種方法各有利弊,實際生產中按需選擇。如果要等待ISR副本復活,雖然可以保證一致性,但可能需要很長時間。而如果選擇立即可用的副本,則很可能該副本並不一致。

2.6 生產者和消費者

(1)生產者

生產者發佈數據到他們所選擇的主題。生產者負責選擇把記錄分配到主題中的哪個分區。這可以使用輪詢算法( round-robin)進行簡單地平衡負載,也可以根據一些更復雜的語義分區算法(比如基於記錄一些鍵值)來完成。

(2)消費者

消費者以消費羣(consumer group)的名稱來標識自己,每個發佈到主題的消息都會發送給訂閱了這個主題的消費羣裏面的一個消費者實例,即一個消費羣只發送一次。消費者的實例可以在單獨的進程或單獨的機器上。

 

 

上圖中兩個服務器的Kafka集羣具有四個分區(P0-P3)和兩個消費羣。A消費羣有兩個消費者,B羣有四個。更常見的是,我們會發現主題有少量的消費羣,每一個都是“邏輯上的訂閱者”。每組都是由很多消費者實例組成,從而實現可擴展性和容錯性。這只不過是發佈 – 訂閱模式的再現,區別是這裏的訂閱者是一組消費者而不是一個單一的進程的消費者。

Kafka消費羣的實現方式是通過分割分區給每個Consumer實例實現的,使每個實例在任何時間點的都可以“公平分享”獨佔的分區。維持消費羣中的成員關係的這個過程是通過Kafka動態協議處理。如果新的實例加入該組,他將接管該組的其他成員的一些分區; 如果一個實例死亡,其分區將被分配到剩餘的實例。

Kafka只保證一個分區內的消息有序,不能保證一個主題的不同分區之間的消息有序。分區的消息有序與依靠主鍵進行數據分區的能力相結合足以滿足大多數應用的要求。但是,如果你想要保證所有的消息都絕對有序可以只爲一個主題分配一個分區,雖然這將意味着每個消費羣同時只能有一個消費進程在消費。

3 、數據可靠性與一致性

3.1 Partition Recovery機制

每個Partition會在磁盤記錄一個RecoveryPoint,記錄已經flush到磁盤的最大offset。當broker fail 重啓時,會進行loadLogs。 首先會讀取該Partition的RecoveryPoint,找到包含RecoveryPoint的segment及以後的segment, 這些segment就是可能沒有完全flush到磁盤segments。然後調用segment的recover,重新讀取各個segment的msg,並重建索引。

優點

• 以segment爲單位管理Partition數據,方便數據生命週期的管理,刪除過期數據簡單。

• 在程序崩潰重啓時,加快recovery速度,只需恢復未完全flush到磁盤的segment。

• 通過index中offset與物理偏移映射,用二分查找能快速定位msg,並且通過分多個Segment,每個index文件很小,查找速度更快。

3.2 Partition Replica同步機制

• Partition的多個replica中一個爲Leader,其餘爲follower
• Producer只與Leader交互,把數據寫入到Leader中
• Followers從Leader中拉取數據進行數據同步
• Consumer只從Leader拉取數據

ISR:in-sync replica,已同步的副本。準確的定義是“所有不落後的replica集合”。不落後有兩層含義:距離上次FetchRequest的時間不大於某一個值或落後的消息數不大於某一個值, Leader失敗後會從ISR中選取一個Follower做Leader。

3.4 消息的順序消費問題

在說到消息中間件的時候,我們通常都會談到一個特性:消息的順序消費問題。這個問題看起來很簡單:Producer發送消息1, 2, 3;Consumer按1, 2, 3順序消費。但實際情況卻是:無論RocketMQ,還是Kafka,缺省都不保證消息的嚴格有序消費!困難如下:

(1)Producer

發送端不能異步發送,異步發送在發送失敗的情況下,就沒辦法保證消息順序。比如你連續發了1,2,3。 過了一會,返回結果1失敗,2, 3成功。你把1再重新發送1遍,這個時候順序就亂掉了。

(2)存儲端

對於存儲端,要保證消息順序,會有以下幾個問題:

消息不能分區。也就是1個topic,只能有1個隊列。在Kafka中,它叫做partition;在RocketMQ中,它叫做queue。 如果你有多個隊列,那同1個topic的消息,會分散到多個分區裏面,自然不能保證順序。

即使只有1個隊列的情況下,會有第2個問題。該機器掛了之後,能否切換到其他機器?也就是高可用問題。比如你當前的機器掛了,上面還有消息沒有消費完。此時切換到其他機器,可用性保證了。但消息順序就亂掉了。要想保證,一方面要同步複製,不能異步複製;另1方面得保證,切機器之前,掛掉的機器上面,所有消息必須消費完了,不能有殘留。很明顯,這個很難。

(3)接收端

對於接收端,不能並行消費,也即不能開多線程或者多個客戶端消費同1個隊列。

3.5 Producer發送消息的配置

3.5.1 同步模式

kafka有同步(sync)、異步(async)以及oneway這三種發送方式,某些概念上區分也可以分爲同步和異步兩種,同步和異步的發送方式通過producer.type參數指定,而oneway由request.require.acks參數指定。

producer.type的默認值是sync,即同步的方式。這個參數指定了在後臺線程中消息的發送方式是同步的還是異步的。如果設置成異步的模式,可以運行生產者以batch的形式push數據,這樣會極大的提高broker的性能,但是這樣會增加丟失數據的風險。

3.5.2 異步模式

對於異步模式,還有4個配套的參數,如下:

 

 

3.5.3 oneway

oneway是隻顧消息發出去而不管死活,消息可靠性最低,但是低延遲、高吞吐,這種對於某些完全對可靠性沒有要求的場景還是適用的,即request.required.acks設置爲0。

3.5.4 消息可靠性級別

當Producer向Leader發送數據時,可以通過request.required.acks參數設置數據可靠性的級別:

• 0: 不論寫入是否成功,server不需要給Producer發送Response,如果發生異常,server會終止連接,觸發Producer更新meta數據;

• 1: Leader寫入成功後即發送Response,此種情況如果Leader fail,會丟失數據

• -1: 等待所有ISR接收到消息後再給Producer發送Response,這是最強保證

僅設置acks=-1也不能保證數據不丟失,當Isr列表中只有Leader時,同樣有可能造成數據丟失。要保證數據不丟除了設置acks=-1, 還要保 證ISR的大小大於等於2,具體參數設置:

• (1)request.required.acks: 設置爲-1 等待所有ISR列表中的Replica接收到消息後採算寫成功;
• (2)min.insync.replicas: 設置爲大於等於2,保證ISR中至少有兩個Replica

Producer要在吞吐率和數據可靠性之間做一個權衡。

3.5.5 一般配置

 

 

4、 應用場景

4.1 消息系統

消息處理模型歷來有兩種:

隊列模型:一組消費者可以從服務器讀取記錄,每個記錄都會被其中一個消費者處理,爲保障消息的順序,同一時刻只能有一個進程進行消費。

發佈-訂閱模型:記錄被廣播到所有的消費者。

Kafka的消費羣的推廣了這兩個概念。消費羣可以像隊列一樣讓消息被一組進程處理(消費羣的成員),與發佈 – 訂閱模式一樣,Kafka可以讓你發送廣播消息到多個消費羣。

Kafka兼顧了消息的有序性和併發處理能力。傳統的消息隊列的消息在隊列中是有序的,多個消費者從隊列中消費消息,服務器按照存儲的順序派發消息。然而,儘管服務器是按照順序派發消息,但是這些消息記錄被異步傳遞給消費者,消費者接收到的消息也許已經是亂序的了。這實際上意味着消息的排序在並行消費中都將丟失。消息系統通常靠 “排他性消費”( exclusive consumer)來解決這個問題,只允許一個進程從隊列中消費,當然,這意味着沒有並行處理的能力。

Kafka做的更好。通過一個概念:並行性-分區-主題實現主題內的並行處理,Kafka是能夠通過一組消費者的進程同時提供排序保證和並行處理以及負載均衡的能力:

(1)排序保障

每個主題的分區指定給每個消費羣中的一個消費者,使每個分區只由該組中的一個消費者所消費。通過這樣做,我們確保消費者是一個分區唯一的讀者,從而順序的消費數據。

(2)並行處理

因爲有許多的分區,所以負載還能夠均衡的分配到很多的消費者實例上去。但是請注意,一個消費羣的消費者實例不能比分區數量多,因爲分區數代表了一個主題的最大併發數,消費者的數量高於這個數量意義不大。

4.2 日誌採集

大多數時候,我們的log都會輸出到本地的磁盤上,排查問題也是使用linux命令來搞定,如果web程序組成負載集羣,那麼就有多臺機器,如果有幾十臺機器,幾十個服務,那麼想快速定位log問題和排查就比較麻煩了,所以很有必要有一個統一的平臺管理log,現在大多數公司的套路都是收集重要應用的log集中到kafka中,然後在分別導入到es和hdfs上,一個做實時檢索分析,另一個做離線統計和數據備份。如何能快速收集應用日誌到kafka中?

方法一:使用log4j的集成包

kafka官網已經提供了非常方便的log4j的集成包 kafka-log4j-appender,我們只需要簡單配置log4j文件,就能收集應用程序log到kafka中。

 

 

注意,需要引入maven的依賴包:

 

 

非常簡單,一個maven依賴加一個log4j配置文件即可,如果依然想寫入log到本地 文件依然也是可以的,這種方式最簡單快速,但是默認的的log日誌是一行一行的純文本,有些場景下我們可能需要json格式的數據。

方法二: 重寫Log4jAppender

重寫Log4jAppender,自定義輸出格式,支持json格式,如果是json格式的數據打入到kafka中,後續收集程序可能就非常方便了,直接拿到json就能入到mongodb或者es中,如果打入到kafka中的數據是純文本,那麼收集程序,可能需要做一些etl,解析其中的一些字段然後再入到es中,所以原生的輸出格式,可能稍不靈活,這樣就需要我們自己寫一些類,然後達到靈活的程度,github連接:https://github.com/qindongliang/log_to_kafka感興趣的朋友可以看下。

總結:

(1)方法一簡單快速,不支持json格式的輸出,打到kafka的消息都是原樣的log日誌信息

(2)方法二稍微複雜,需要自己擴展log收集類,但支持json格式的數據輸出,對於想落地json數據直接到存儲系統中是非常適合的。

此外需要注意,在調試的時候log發送數據到kafka模式最好是同步模式的否則你控制檯打印的數據很有可能不會被收集kafka中,程序就停止了。生產環境最好開啓異步發送數據模式,因爲內部是批量的處理,所以能提升吞吐,但有一定的輕微延遲。

4.3 流處理

只是讀,寫,以及儲存數據流是不夠的,目的是能夠實時處理數據流。在Kafka中,流處理器是從輸入的主題連續的獲取數據流,然後對輸入進行一系列的處理,並生產連續的數據流到輸出主題。

這些簡單處理可以直接使用生產者和消費者的API做到。然而,對於更復雜的轉換Kafka提供了一個完全集成的流API。這允許應用程序把一些重要的計算過程從流中剝離或者加入流一起。這種設施可幫助解決這類應用面臨的難題:處理雜亂的數據,改變代碼去重新處理輸入,執行有狀態的計算等。流API建立在Kafka提供的核心基礎單元之上:它使用生產者和消費者的API進行輸入輸出,使用Kafka存儲有狀態的數據,並使用羣組機制在一組流處理實例中實現容錯。

把功能組合起來

消息的傳輸,存儲和流處理的組合看似不尋常,卻是Kafka作爲流處理平臺的關鍵。像HDFS分佈式文件系統,允許存儲靜態文件進行批量處理。像這樣的系統允許存儲和處理過去的歷史數據。傳統的企業消息系統允許處理您訂閱後才抵達的消息。這樣的系統只能處理將來到達的數據。

Kafka結合了這些功能,這種結合對Kafka作爲流應用平臺以及數據流處理的管道至關重要。通過整合存儲和低延遲訂閱,流處理應用可以把過去和未來的數據用相同的方式處理。這樣一個單獨的應用程序,不但可以處理歷史的,保存的數據,當它到達最後一條記錄不會停止,繼續等待處理未來到達的數據。這是泛化了的流處理的概念,包括了批處理應用以及消息驅動的應用。同樣,流數據處理的管道結合實時事件的訂閱使人們能夠用Kafka實現低延遲的管道; 可靠的存儲數據的能力使人們有可能使用它傳輸一些重要的必須保證可達的數據。可以與一個定期加載數據的線下系統集成,或者與一個因爲維護長時間下線的系統集成。流處理的組件能夠保證轉換(處理)到達的數據。

5、Kafka與ActiveMQ對比

首先,Active MQ與Kafka的相同點只有一個,就是都是消息中間件。其他沒有任何相同點。

5.1 consumer的不同

(1)AMQ消費完的消息會被清理掉

AMQ無論在standalone還是分佈式的情況下,都會使用mysql作爲存儲,多一個consumer線程去消費多個queue, 消費完的message會在mysql中被清理掉。

(2)AMQ的消費邏輯在Broker中完成

作爲AMQ的consume clinet的多個consumer線程去消費queue,AMQ Broker會接收到這些consume線程,阻塞在這裏,有message來了就會進行消費,沒有消息就會阻塞在這裏。具體消費的邏輯也就是處理這些consumer線程都是AMQ Broker那面處理。

kafka是message都存在partition下的segment文件裏面,有offsite偏移量去記錄那條消費了,哪條沒消費。某個consumer group下consumer線程消費完就會,這個consumer group 下的這個consumer對應這個partition的offset+1,kafka並不會刪除這條已經被消費的message。其他的consumer group也可以再次消費這個message。在high level api中offset會自動或手動的提交到zookeeper上(如果是自動提交就有可能處理失敗或還沒處理完就提交offset+1了,容易出現下次再啓動consumer group的時候這條message就被漏了),也可以使用low level api,那麼就是consumer程序中自己維護offset+1的邏輯。kafka中的message會定期刪除。

(3)Kafka有consumer group的概念,AMQ沒有。

一個consumer group下有多個consumer,每個consumer都是一個線程,consumer group是一個線程組。每個線程組consumer group之間互相獨立。同一個partition中的一個message只能被一個consumer group下的一個consumer線程消費,因爲消費完了這個consumer group下的這個consumer對應的這個partition的offset就+1了,這個consumer group下的其他consumer還是這個consumer都不能在消費了。 但是另外一個consumer group是完全獨立的,可以設置一個from的offset位置,重新消費這個partition。

5.2 關於存儲結構

ActiveMQ的消息持久化機制有JDBC,AMQ,KahaDB和LevelDB

Kafka是文件存儲,每個topic有多個partition,每個partition有多個replica副本(每個partition和replica都是均勻分配在不同的kafka broker上的)。每個partition由多個segment文件組成。這些文件是順序存儲的。因此讀取和寫入都是順序的,因此,速度很快,省去了磁盤尋址的時間。

很多系統、組件爲了提升效率一般恨不得把所有數據都扔到內存裏,然後定期flush到磁盤上;而Kafka決定直接使用頁面緩存;但是隨機寫入的效率很慢,爲了維護彼此的關係順序還需要額外的操作和存儲,而線性的順序寫入可以避免磁盤尋址時間,實際上,線性寫入(linear write)的速度大約是300MB/秒,但隨即寫入卻只有50k/秒,其中的差別接近10000倍。這樣,Kafka以頁面緩存爲中間的設計在保證效率的同時還提供了消息的持久化,每個consumer自己維護當前讀取數據的offset(也可委託給zookeeper),以此可同時支持在線和離線的消費。

5.3 關於使用場景與吞吐量

ActiveMQ用於企業消息中間件,使得業務邏輯和前端處理邏輯解耦。AMQ的吞吐量不大,zuora的AMQ就是用作jms來使用。AMQ吞吐量不夠,並且持久化message數據通過jdbc存在mysql,寫入和讀取message性能太低。而Kafka的吞吐量非常大。

5.4 push/pull 模型

對於消費者而言有兩種方式從消息中間件獲取消息:

①Push方式:由消息中間件主動地將消息推送給消費者,採用Push方式,可以儘可能快地將消息發送給消費者;②Pull方式:由消費者主動向消息中間件拉取消息,會增加消息的延遲,即消息到達消費者的時間有點長

但是,Push方式會有一個壞處:如果消費者的處理消息的能力很弱(一條消息需要很長的時間處理),而消息中間件不斷地向消費者Push消息,消費者的緩衝區可能會溢出。

AMQ的Push消費

ActiveMQ使用PUSH模型, 對於PUSH,broker很難控制數據發送給不同消費者的速度。AMQ Broker將message推送給對應的BET consumer。ActiveMQ用prefetch limit 規定了一次可以向消費者Push(推送)多少條消息。當推送消息的數量到達了perfetch limit規定的數值時,消費者還沒有向消息中間件返回ACK,消息中間件將不再繼續向消費者推送消息。

AMQ的Pull消費

ActiveMQ prefetch limit 設置成0意味着什麼?意味着此時,消費者去輪詢消息中間件獲取消息。不再是Push方式了,而是Pull方式了。即消費者主動去消息中間件拉取消息。

那麼,ActiveMQ中如何採用Push方式或者Pull方式呢?從是否阻塞來看,消費者有兩種方式獲取消息。同步方式和異步方式。

同步方式使用的是ActiveMQMessageConsumer的receive()方法。而異步方式則是採用消費者實現MessageListener接口,監聽消息。使用同步方式receive()方法獲取消息時,prefetch limit即可以設置爲0,也可以設置爲大於0。

prefetch limit爲零 意味着:“receive()方法將會首先發送一個PULL指令並阻塞,直到broker端返回消息爲止,這也意味着消息只能逐個獲取(類似於Request<->Response)”。

prefetch limit 大於零 意味着:“broker端將會批量push給client 一定數量的消息(<= prefetch),client端會把這些消息(unconsumedMessage)放入到本地的隊列中,只要此隊列有消息,那麼receive方法將會立即返回,當一定量的消息ACK之後,broker端會繼續批量push消息給client端。”

當使用MessageListener異步獲取消息時,prefetch limit必須大於零了。因爲,prefetch limit 等於零 意味着消息中間件不會主動給消費者Push消息,而此時消費者又用MessageListener被動獲取消息(不會主動去輪詢消息)。這二者是矛盾的。

Kafka只有Pull消費方式

Kafka使用PULL模型,PULL可以由消費者自己控制,但是PULL模型可能造成消費者在沒有消息的情況下盲等,這種情況下可以通過long polling機制緩解,而對於幾乎每時每刻都有消息傳遞的流式系統,這種影響可以忽略。Kafka 的 consumer 是以pull的形式獲取消息數據的。 pruducer push消息到kafka cluster ,consumer從集羣中pull消息。

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