這絕對是2019年kafka架構與原理最全面解析的文章,不看後悔

一、 簡介前端

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

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

首先,明確幾個概念:web

• Kafka運行在一個或多個服務器上。面試

• Kafka集羣分類存儲的記錄流被稱爲主題(Topics)。算法

• 每一個消息記錄包含一個鍵,一個值和時間戳。sql

Kafka有四個核心API:mongodb

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

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

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

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

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

二、 架構

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.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中,因此原生的輸出格式,可能稍不靈活,這樣就須要咱們本身寫一些類,而後達到靈活的程度。

總結:

(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實現低延遲的管道; 可靠的存儲數據的能力令人們有可能使用它傳輸一些重要的必須保證可達的數據。能夠與一個按期加載數據的線下系統集成,或者與一個由於維護長時間下線的系統集成。流處理的組件可以保證轉換(處理)到達的數據。

五、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消息。

如何學習呢?有沒有免費資料?

我本身收集了一些Java資料,裏面就包涵了一些BAT面試資料,以及一些 Java 高併發、分佈式、微服務、高性能、源碼分析、JVM等技術資料

資料獲取方式:請加羣BAT架構技術交流羣:171662117
圖片描述
圖片描述

今天免費分享 免費分享!

轉發 !

轉發 !

相關文章
相關標籤/搜索