訊息佇列-如何保證訊息的不被重複消費(如何保證訊息消費的冪等性)

小碼code發表於2021-11-19

在訊息傳遞過程中,如果出現傳遞失敗的情況,傳送會執行重試,重試可能會產生重複的訊息。對系統來說,如果沒有對重複消費進行處理,會導致系統資料發生錯誤。
比如,一個訂單系統,訂單建立成功後,把資料寫入統計資料庫,如果發生重複統計,會導致資料庫資料錯誤。

解決訊息重複消費,其實就是保證訊息的消費冪等性。

冪等性的定義:

多次執行所產生的影響均與一次執行的影響相同。
所以需要從業務邏輯上設計,將消費的業務邏輯設計成冪等性。

利用資料庫的唯一約束

在進行訊息消費,需要取一個唯一個標識,比如 id 作為唯一約束欄位,先新增資料,如果新增失敗,後續做錯誤提示,或者不做後續操作。

Redis 設定全域性唯一id

每次生產者傳送訊息前設定一個全域性唯一id放在訊息體重,並存放的 redis 裡,在消費端介面上先找在redis 檢視是否存在全域性id,如果存在,呼叫消費介面並刪除全域性id,如果不存在,不做後續操作。

多版本(樂觀鎖)機制

給業務資料新增一個版本號,每次更新資料前,比如當前版本和訊息中的版本是否一致,如果一致就更新資料並且版本號+1,如果不一致就不跟新。這有點類似樂觀鎖處理機制。

總結

設計冪等需要根據具體的業務場景,如果是併發量比較大的系統,資料庫一般支撐不了這麼大的併發,需要使用 Redis 快取處理。而併發不大的系統可以選擇資料庫。

如果覺得文章對你有幫助的話,請點個推薦吧!

相關文章