關於MQ的幾件小事(三)如何保證訊息不重複消費

一條路上的鹹魚發表於2019-05-22

1.冪等性

冪等(idempotent、idempotence)是一個數學與計算機學概念,常見於抽象代數中。 在程式設計中一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等函式,或冪等方法,是指可以使用相同引數重複執行,並能獲得相同結果的函式。這些函式不會影響系統狀態,也不用擔心重複執行會對系統造成改變。例如,“setTrue()”函式就是一個冪等函式,無論多次執行,其結果都是一樣的.更復雜的操作冪等保證是利用唯一交易號(流水號)實現.

簡單來說,冪等性就是一個資料或者一個請求,給你重複來了多次,你得確保對應的資料是不會改變的,不能出錯。

2.出現重複消費場景

(1)首先,比如rabbitmq、rocketmq、kafka,都有可能會出現訊息重複消費的問題。因為這個問題通常不是由mq來保證的,而是消費方自己來保證的。
(2)舉例kafka來說明重複消費問題 kafka有一個叫做offset的概念,就是每個訊息寫進去,都有一個offset代表他的序號,然後consumer消費了資料之後,每隔一段時間,會把自己消費過的訊息的offset提交一下,代表我已經消費過了,下次就算重啟,kafka就會讓消費者從上次消費到的offset來繼續消費。

但是萬事總有例外,如果consumer消費了資料,還沒來得及傳送自己已經消費的訊息的offset就掛了,那麼重啟之後就會收到重複的資料。

kafka重複消費示意圖.png

3.保證冪等性(重複消費)

要保證訊息的冪等性,這個要結合業務的型別來進行處理。下面提供幾個思路供參考:

(1)、可在記憶體中維護一個set,只要從訊息佇列裡面獲取到一個訊息,先查詢這個訊息在不在set裡面,如果在表示已消費過,直接丟棄;如果不在,則在消費後將其加入set當中。

(2)、如何要寫資料庫,可以拿唯一鍵先去資料庫查詢一下,如果不存在在寫,如果存在直接更新或者丟棄訊息。

(3)、如果是寫redis那沒有問題,每次都是set,天然的冪等性。

(4)、讓生產者傳送訊息時,每條訊息加一個全域性的唯一id,然後消費時,將該id儲存到redis裡面。消費時先去redis裡面查一下有麼有,沒有再消費。

(5)、資料庫操作可以設定唯一鍵,防止重複資料的插入,這樣插入只會報錯而不會插入重複資料。

上一篇《如何保證訊息佇列的高可用
下一篇《如何防止資料佇列資料丟失

相關文章