要想實現訊息有序,需要從 producer 和 consumer 兩方面來考慮。
首先,producer 生產訊息的時候就必須要有序。
然後,consumer 消費的時候,也要按順序來,不能亂。
producer 有序
像 rabbitmq 這類普通的訊息系統,佇列結構簡單,producer 向佇列中傳送訊息就完了,進入佇列的訊息肯定是有序的。
kafka 比較特殊,因為它的乙個 topic(就是佇列的概念)實際上分為了多個 partition。
producer 傳送訊息的時候,是分散在不同 partition 的。
producer 按順序發訊息,但進入 kafka topic 之後,這些訊息就不一定進到哪個 partition 了,所以順序肯定是亂的。
如果想 topic 內的訊息全域性有序,就只能設定乙個 partition 了,這就變成了 rabbitmq 那種結構。
但這種結構不符合 kafka 的設計理念,topic 只有乙個 partition 就失去了擴充套件性。
kafka 還支援一種區域性有序的方式,就是把某一類的訊息都放入同乙個 partition,就保證了這組訊息的順序。
在發訊息的時候指定 partition key,kafka 對其進行 hash 計算,根據計算結果決定放入哪個 partition。
所以,partition key 一樣的訊息肯定是在一起的。
例如使用使用者 id 做 key,這樣同乙個使用者的訊息肯定是在一起的,就保證了這一組的訊息的有序。
consumer 有序
mq 內訊息有序,那麼 consumer 自然也是按順序接收的。
但是,如果使用了多個 consumer,就可能出現亂序。
例如 rabbitmq 的乙個 queue 有 3個 consumer,雖然會按順序接收到訊息,但是它們各自的處理速度是不同的,所以,出來的結果很可能是亂序的。
如果想嚴格按順序來,就只能使用乙個 consumer。
如果可以使用區域性有序,那麼就把之前的乙個佇列拆為多個佇列,就像 kafka 的 partition key 一樣,把同組資料放入同乙個佇列。
kafka 中乙個 partition 只能對應乙個 consumer,但如果 consumer 使用了多執行緒,就和多個 consumer 乙個效果了,還是會造成亂序。
這樣的話就需要進一步細化訊息的分組。
為每個執行緒建立乙個記憶體佇列,consumer 收到訊息後,把同組的訊息都放在同乙個記憶體佇列,由同乙個執行緒處理即可。
小結一下,訊息的有序需要 producer 和 consumer 都有序。
rabbitmq 的佇列結構簡單,producer 傳送的訊息是有序的。但 kafka 特殊,乙個 topic 有多個 partition,如果要求全域性有序,就只能使用乙個 partition。
如果可以接受區域性有序,就可以為訊息設定 partition key,其 hash 計算結果相同的訊息都會在同乙個 partition。
consumer 消費時需要注意多 consumer 的情況,例如多個消費執行緒。
可以在 consumer 收到訊息後再細化分組,同組的訊息交給同乙個消費執行緒處理。
推薦閱讀
oauth2 **
輕鬆理解 kubernetes 的核心概念
開發者必須要了解的架構技術趨勢:service mesh
如何保證mq的有序性 訊息佇列如何保證順序性?
主要思路有兩種 1 單執行緒消費來保證訊息的順序性 2 對訊息進行編號,消費者處理時根據編號判斷順序。1 rabbitmq 問題分析 如圖,data1 和 data2 是有順序的,必須 data1 先執行,data2 後執行 這兩個資料被不同的消費者消費到了,可能 data2 先執行,data1 後...
如何保證訊息佇列訊息的順序性
舉個例子 有乙個mysql binlog 同步系統,壓力是非常大的,日同步資料達到了上億級別,就是將資料從乙個 mysql 庫當中原封不動的同步到另乙個 mysql 庫當中去 比較常見的就是大資料組需要幹的事情 假設在 mysql 當中增刪改了一條資料,對應的生產了三條 增刪改的 binlog 日誌...
訊息佇列訊息順序性
原本資料應該是資料1 資料2 資料3的順序儲存到庫里,但是消費者對資料2操作優先了。導致訊息的資料錯亂儲存入庫 如果存在多個消費者,那麼每個消費者分別乙個queue 這樣每個消費者消費的queue裡就有順序了 1個partition 對應乙個消費者,那麼消費者中開多個執行緒去消費資料,那麼就會出現訊...