摘抄自:https://blog.csdn.net/weixin_42494845/article/details/111408725
kafka的Consumer均衡算法
在說順序性這個問題之前,我們要先搞明白的是消費者是怎么消費分區上的數據。
我們這里不詳細討論該算法,這不是本文的重點。
簡單的說:
kafka的消費組的組員最多增加到和partition數量一致,超過的組員只會占用資源,而不起作用;
kafka的partition的個數一定要大於消費組組員的個數,並且partition的個數對於消費組組員取模一定要為0,不然有些消費者會占用資源卻不起作用;
我們一般將消費組里組員的個數設置為和partition的數量相同。
消息順序錯亂問題
我們都知道Kafka是分布式多partition的,它會將一個topic中的消息盡可能均勻的分發到每個partition上。那么問題就來了,這樣怎么保證同一個topic消息的順序呢?
由於消費者是並行處理消息的,我們就無法保證消息的順序性。
如何發送順序消息
這個其實也很簡單。
kafka可以通過partitionKey,將某類消息寫入同一個partition,一個partition只能對應一個消費線程,以保證數據有序。
也就是說生產者在寫消息的時候,可以指定一個 key,比如說我們指定了某個訂單 id 作為 key,那么這個訂單相關的數據,一定會被分發到同一個 partition 中去,而且這個 partition 中的數據一定是有順序的。
Kafka如何保證單partition有序?
producer發消息到隊列時,通過加鎖保證有序。
那么是否有這樣一個問題呢?
先后兩條消息發送時,前一條消息發送失敗,后一條消息發送成功,然后失敗的消息重試后發送成功,造成亂序。
為了解決重試機制引起的消息亂序為實現Producer的冪等性,Kafka引入了Producer ID(即PID)和Sequence Number。
對於每個PID,該Producer發送消息的每個<Topic, Partition>都對應一個單調遞增的Sequence Number。
同樣,Broker端也會為每個<PID, Topic, Partition>維護一個序號,並且每Commit一條消息時將其對應序號遞增。
對於接收的每條消息,如果其序號比Broker維護的序號大一,則Broker會接受它,否則將其丟棄
如果消息序號比Broker維護的序號差值比一大,說明中間有數據尚未寫入,即亂序,此時Broker拒絕該消息
如果消息序號小於等於Broker維護的序號,說明該消息已被保存,即為重復消息,Broker直接丟棄該消息
發送失敗后會重試,這樣可以保證每個消息都被發送到broker
消費者從 partition 中取出來數據的時候,也一定是有順序的。到這里,順序還是 ok 的,沒有錯亂。
但是消費者這里還是可能會有多個線程來並發來處理消息,因為如果消費者是單線程消費數據,那么這個吞吐量太低了。而多個線程並發的話,順序可能就亂掉了。
解決方案
消費者端創建多個內存隊列,具有相同 key 的數據都路由到同一個內存 隊列;然后每個線程分別消費一個內存隊列即可,這樣就能保證順序性。
————————————————
版權聲明:本文為CSDN博主「紅丶」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_42494845/article/details/111408725