跳轉到

如何避免重複消費訊息

重複發送

重送是從 Producer 這端保證訊息不會遺失。如果發送訊息成功,但在記錄成功前程式崩了/或因為網路問題,導致 Broker 儲存了訊息,但是呼叫方失敗了,Producer 為了保證訊息不丟失,會再次重送這個失敗的消息導致重複發送。

img

如果要避免這種情況,需要設置 producer configuration parameters:

parameter value description
enable.idempotence true

img

重複消費

Consumer 一般在消費訊息時,都建議處理完業務後,手動提交 offset;但是在提交 offset 的時候,因為某些原因程序崩了。Consumer 再次重啟後,會繼續消費上次未提交的訊息導致重複消費。

解決方法:冪等性處理

強校驗

flowchart LR
    A[開始消費] --> B{是否擁有key}
    B  -- Yes --> C[結束]
    subgraph T[Transaction]
    D[業務處理]-->E[插入唯一key]
    end
    B  -- No --> D
    E --> F{是否執行成功}
    F -- Yes --> G[結束]
    F -- No --> A
優點 缺點
在併發情況下,只會嚴格執行一次。資料庫唯一性+事務回滾能保證業務只執行一次; 不會存在冪等校驗穿透的問題 處理速度較慢: 處理效能上和 redis 方案比起來,慢一個數量級。畢竟有事務加持;另外插入唯一資料時極大可能讀磁碟資料,進行唯一性校驗
可提供查詢流水功能:處理流水記錄的持久化,在某些異常問題排查情況下,還能較為方便的提供查詢記錄 歷史資料需要額外進行清理:如果採用 mysql 進行存儲,歷史記錄資料的清理,需要自己單獨考慮和處理
實現簡單:實現難度還是較簡單的,一個註解能包裹住事務+回滾
適用資金類業務:非常適合涉及資金類業務的防重

Reference