如何保證消息按順序執行

1. 爲什麼要保證順序

消息隊列中的若干消息如果是對同一個數據進行操作,這些操作具有前後的關係,必須要按前後的順序執行,否則就會造成數據異常。舉例:
比如通過 mysql binlog 進行兩個數據庫的數據同步,由於對數據庫的數據操作是具有順序性的,如果操作順序搞反,就會造成不可估量的錯誤。比如數據庫對一條數據依次進行了 插入 -> 更新 -> 刪除操作,這個順序必須是這樣,如果在同步過程中,消息的順序變成了 刪除 -> 插入 -> 更新,那麼原本應該被刪除的數據,就沒有被刪除,造成數據的不一致問題。

2. 出現順序錯亂的場景

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

rabbitmq 消息順序錯亂第一種情況示意圖. png

②一個 queue 對應一個 consumer,但是 consumer 裏面進行了多線程消費,這樣也會造成消息消費順序錯誤。

abbitmq 消息順序錯亂第二種情況示意圖. png

(2)kafka
①kafka 一個 topic,一個 partition,一個 consumer,但是 consumer 內部進行多線程消費,這樣數據也會出現順序錯亂問題。

kafka 消息順序錯亂第一種情況示意圖. png

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

kafka 消息順序錯亂第二種情況示意圖..png

3. 保證消息的消費順序

(1)rabbitmq
①拆分多個 queue,每個 queue 一個 consumer,就是多一些 queue 而已,確實是麻煩點;這樣也會造成吞吐量下降,可以在消費者內部採用多線程的方式取消費。

一個 queue 對應一個 consumer

②或者就一個 queue 但是對應一個 consumer,然後這個 consumer 內部用內存隊列做排隊,然後分發給底層不同的 worker 來處理

一個 queue 對應一個 consumer,採用多線程. png

(2)kafka
①確保同一個消息發送到同一個 partition,一個 topic,一個 partition,一個 consumer,內部單線程消費。

單線程保證順序. png

②寫 N 個內存 queue,然後 N 個線程分別消費一個內存 queue 即可

多線程保證順序. png

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://www.jianshu.com/p/02fdcb9e8784