為了防止消息重復消費導致業務處理異常,輕量消息隊列(原 MNS)的消費者在接收到消息后,需要根據業務唯一標識對消息做冪等處理。本文介紹消費冪等的概念、適用場景以及處理方法。
什么是消費冪等
在消息隊列場景中,消費冪等處理是指即使因為某些原因(如網絡問題、系統故障等)導致同一條消息被多次發送給消費者,通過冪等性設計也能保證最終的業務邏輯只被執行一次,避免因為重復消費而導致數據錯誤或業務結果不一致的情況。
例如,在支付場景下,Consumer消費扣款消息,對一筆訂單執行扣款操作,扣款金額為100元。如果因網絡不穩定、系統故障等原因導致扣款消息重復投遞,Consumer重復消費了該扣款消息,但最終的業務結果是只扣款一次,扣費100元,且用戶的扣款記錄中對應的訂單只有一條扣款流水,不會多次扣除費用。那么這次扣款操作是符合要求的,整個消費過程實現了冪等處理。
適用場景
冪等性在分布式系統中尤為重要,當系統出現網絡抖動、系統故障、重復發送等異常時,消息可能會被重復消費,冪等性可以在消息重復時提高系統的可靠性和一致性。消息重復的可能原因如下:
消費處理耗時超過消息不可見時間:當某個消費者A處理消息的時長超過了不可見時間,消息會重新被投遞給消費者B,這種情況下會導致消費者A和B重復處理同一條消息。
網絡異常或抖動:消息已被消費者處理成功,但網絡異常導致
DeleteMessage
請求異常,消息在不可見時間之后會被重新投遞給消費者。消息隊列服務器或消費者服務重啟:消息已被消費者處理成功,但消息隊列服務器或者消費者服務重啟導致
DeleteMessage
請求處理失敗,消息在不可見時間之后會被重新投遞給消費者。
處理方法
在消息隊列中,通常以Message ID為冪等鍵對消息進行冪等處理,但是由于不同的Message ID對應的消息內容可能相同,有可能出現沖突(重復)的情況,所以真正安全的冪等處理不建議以Message ID作為處理依據。輕量消息隊列(原 MNS)建議您以業務唯一標識作為冪等處理的關鍵依據。
唯一標識符:為每個消息分配一個唯一的標識符,消費者在處理消息時,記錄已處理的業務唯一標識,當再次收到相同的消息時,消費者可以直接跳過不再處理。
數據庫約束:在數據庫中設置唯一約束,當嘗試插入重復數據時會因為違反約束而失敗,從而實現冪等性。
業務狀態機檢查:在處理消息之前,消費者先檢查數據的當前狀態,比如數據是否已存在或已被處理。如果是,則直接返回,不再執行后續操作。
合并操作:對于某些操作,可以通過合并的方式來確保冪等性,即使執行多次,也只會產生一次最終結果。