RabbitMQ 和 Kafka 如何保證消息順序執行?

一、爲什麼要保證順序

例如,業務上產生三條消息,分別是對數據的增加、修改、刪除,而如果沒有保證順序消費,結果可能是刪除、修改、增加,本來數據最終要刪除、結果變成增加。

二、RabbitMQ 順序消費模式

一個 Queue,有多個 Consumer 去消費,這樣就會造成順序的錯誤,Consumer 從 MQ 裏面讀取數據是有序的,但是每個 Consumer 的執行時間是不固定的,無法保證先讀到消息的 Consumer 一定先完成操作,這樣就會出現消息並沒有按照順序執行,造成數據順序錯誤。

解決方案:

一個 Queue 對應一下 Consumer,把需要保證順序的 message 都發送到一個 Queue 當中,關閉 autoack,prefetchCount=1,每次只消費一條信息,處理過後進行手工 ack,然後接收下一條 message,只是由一個 Consumer 進行處理。

多數業務場景下,可以做局部順序,創建多個隊列,同一業務 id 的消息發送到同一個消息隊列,這樣隊列數增加,消費者數量也會增加 了。

拆分多個 Queue,每個 Queue 一個 Consumer,就是多一些 Queue 而已。

首先,我們在 RabbitMQ 中會建立有相同前綴的隊列,後面跟着隊列編號。然後,集羣中的不同應用會分別監聽這兩個有着不同編號的隊列。當在 A 發送信息時,我們會對信息做一次簡單的哈希:

m = hash(id) mod n

這裏,id 是訂單的標識。n 是集羣中 B 所在業務系統部署的數量。最終的 m 是我們需要發送到的目的隊列編號。

假設,hash(id) 的結果爲 2000,n 爲 2,經過計算 m = 0。此時,A 就會把他和 B 的對話信息都發送到 chat00 的隊列裏。B 收到消息後,就會依次顯示給終端用戶。這樣,聊天亂序的問題就解決了。

三、kafka 順序消費模式

具有順序的數據寫入到了不同的 partition 裏面,不同的消費者去消費,但是每個 consumer 的執行時間是不固定的,無法保證先讀到消息的 consumer 一定先完成操作,這樣就會出現消息並沒有按照順序執行,造成數據順序錯誤。

解決方案:

確保順序消息發送到同一個 partition,一個 topic,一個 partition,一個 consumer,內部單線程消費。

來源:

https://www.toutiao.com/i6936741307201274401/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/4LcvhVOU8Ov_TzogWNs-sA