Kafka 消費者及消費者分區策略


消費方式:

consumer 采用 pull(拉)模式從 broker 中讀取數據。

  push(推)模式很難適應消費速率不同的消費者,因為消息發送速率是由 broker 決定的

它的目標是盡可能以最快速度傳遞消息,但是這樣很容易造成 consumer 來不及處理消息,典型的表現就是拒絕服務以及網絡擁塞。而 pull 模式則可以根據 consumer 的消費能力以適 當的速率消費消息。

  pull 模式不足之處是,如果 kafka 沒有數據,消費者可能會陷入循環中,一直返回空數 據。針對這一點,Kafka 的消費者在消費數據時會傳入一個時長參數 timeout,如果當前沒有 數據可供消費,consumer 會等待一段時間之后再返回,這段時長即為 timeout。

 

 

一個 consumer group 中有多個 consumer,一個 topic 有多個 partition,所以必然會涉及 到 partition 的分配問題,即確定那個 partition 由哪個 consumer 來消費。

Kafka 有三種分配策略,

RoundRobinAssignor分配策略
RangeAssignor(默認)
StickyAssignor分配策略
 

 

一、 RoundRobinAssignor:

第一種例子 所有分區是一個主題

 

 0-6一共7個分區,輪詢給消費者組種的消費者消費。

 

第二個例子 消費者消費多個主題

   

  例如T1三個分區,T2主題也有3個分區,我們的消費者組里有2個消費者。2個消費者都訂閱了主題T1\T2, RoundRobin中 會把兩個主題中當作一個整體, 將分區對象(TopicAndPartition)的hash值排個序,分別給2個消費者。

  但是這種策略存在問題:

  

  如果,同一個消費者組中的A、B兩個消費者,A訂閱T1、T2; B訂閱T2、T3,那么會把T1\T2\T3當作一個整體,就會導致B未訂閱T1也會收到T1的分區;或者同一個消費者組 A訂閱T1,B訂閱T2,也有可能導致A消費T2....會有問題。所以kafka中默認的消費分區策略是range策略。

 

 
二、RangeAssignor:先看訂閱的消費者,再看組。

  7/3 = 2;第一個給三個,后面每個給兩個。 

   存在的問題:可能會導致不均衡。因為range分區策略是按主題來划分。

 

 例如:一個消費者組中A、B兩個消費者,訂閱了主題T1和T2. range是按主題來分別分區的。那么A消費T1的0,1分區,消費T2的0 1分區,隨着主題增多,這里消費者之間消費的分區數將不均衡。

 

再來看一個例子:

  

 

 

A、B消費者屬於同一個消費者組,C是另一個消費者組。A、B訂閱了T1主題,B訂閱了T2主題。C訂閱了T1主題:

如果是RoundRobin 分區策略,把T1、T2的6個對象作為一個整體,往A\B分組發,可能導致A收到T2主題的數據;

所以要用range分區策略:range分區要按主題划分,C單獨消費T1; T1的0、1分區給A  , 2分區給B;

對於T2主題,按主題划分需要先看是誰訂閱了這個主題,然后才考慮組。

 

 

 

消費者分區策略觸發執行時機:

  當消費者數量變化時:例如啟動消費者時,或者添加或者減少消費者個數。

當消費者組里的消費者個數發生變化,都要重新分配分區。

 

三、StickyAssignor分配策略

Kafka從0.11.x版本開始引入這種分配策略,它主要有兩個目的:

1、分區的分配要盡可能的均勻;

2、分區的分配盡可能的與上次分配的保持相同。

當兩者發生沖突時,第一個目標優先於第二個目標

  假設消費組內有3個消費者:C0、C1和C2,它們都訂閱了4個主題:t0、t1、t2、t3,並且每個主題有2個分區,也就是說整個消費組訂閱了t0p0、t0p1、t1p0、t1p1、t2p0、t2p1、t3p0、t3p1這8個分區。最終的分配結果如下:

消費者C0:t0p0、t1p1、t3p0
消費者C1:t0p1、t2p0、t3p1
消費者C2:t1p0、t2p1

  這樣初看上去似乎與采用RoundRobinAssignor策略所分配的結果相同,但事實是否真的如此呢?再假設此時消費者C1脫離了消費組,那么消費組就會執行再平衡操作,進而消費分區會重新分配。  

  如果采用RoundRobinAssignor策略,那么此時的分配結果如下:

消費者C0:t0p0、t1p0、t2p0、t3p0
消費者C2:t0p1、t1p1、t2p1、t3p1

  如分配結果所示,RoundRobinAssignor策略會按照消費者C0和C2進行重新輪詢分配。而如果此時使用的是StickyAssignor策略,那么分配結果為:

消費者C0:t0p0、t1p1、t3p0、t2p0
消費者C2:t1p0、t2p1、t0p1、t3p1

 

  可以看到分配結果中保留了上一次分配中對於消費者C0和C2的所有分配結果並將原來消費者C1的“負擔”分配給了剩余的兩個消費者C0和C2,最終C0和C2的分配還保持了均衡

如果發生分區重分配,那么對於同一個分區而言有可能之前的消費者和新指派的消費者不是同一個,對於之前消費者進行到一半的處理還要在新指派的消費者中再次復現一遍,這顯然很浪費系統資源。StickyAssignor策略如同其名稱中的“sticky”一樣,讓分配策略具備一定的“粘性”,盡可能地讓前后兩次分配相同,進而減少系統資源的損耗以及其它異常情況的發生。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM