MQ如何實現冪等性
一、緣起
如《訊息匯流排訊息必達》所述,MQ訊息必達,架構上有兩個核心設計點:
(1)訊息落地
(2)訊息超時、重傳、確認
再次回顧訊息匯流排核心架構,它由傳送端、服務端、固化儲存、接收端四大部分組成。
為保證訊息的可達性,超時、重傳、確認機制可能導致訊息匯流排、或者業務方收到重複的訊息,從而對業務產生影響。
舉個栗子:
購買會員卡,上游支付系統負責給使用者扣款,下游系統負責給使用者髮卡,通過MQ非同步通知。不管是上半場的ACK丟失,導致MQ收到重複的訊息,還是下半場ACK丟失,導致購卡系統收到重複的購卡通知,都可能出現,上游扣了一次錢,下游發了多張卡。
訊息匯流排的冪等性設計
二、上半場的冪等性設計
MQ訊息傳送上半場,即上圖中的1-3
1,傳送端MQ-client將訊息發給服務端MQ-server
2,服務端MQ-server將訊息落地
3,服務端MQ-server回ACK給傳送端MQ-client
如果3丟失,傳送端MQ-client超時後會重發訊息,可能導致服務端MQ-server收到重複訊息。
此時重發是MQ-client發起的,訊息的處理是MQ-server,為了避免步驟2落地重複的訊息,對每條訊息,MQ系統內部必須生成一個inner-msg-id,作為去重和冪等的依據,這個內部訊息ID的特性是:
(1)全域性唯一
(2)MQ生成,具備業務無關性,對訊息傳送方和訊息接收方遮蔽
有了這個inner-msg-id,就能保證上半場重發,也只有1條訊息落到MQ-server的DB中,實現上半場冪等。
三、下半場的冪等性設計
MQ訊息傳送下半場,即上圖中的4-6
4,服務端MQ-server將訊息發給接收端MQ-client
5,接收端MQ-client回ACK給服務端
6,服務端MQ-server將落地訊息刪除
需要強調的是,接收端MQ-client回ACK給服務端MQ-server,是訊息消費業務方的主動呼叫行為,不能由MQ-client自動發起,因為MQ系統不知道消費方什麼時候真正消費成功。
如果5丟失,服務端MQ-server超時後會重發訊息,可能導致MQ-client收到重複的訊息。
此時重發是MQ-server發起的,訊息的處理是訊息消費業務方,訊息重發勢必導致業務方重複消費(上例中的一次付款,重複髮卡),為了保證業務冪等性,業務訊息體中,必須有一個biz-id,作為去重和冪等的依據,這個業務ID的特性是:
(1)對於同一個業務場景,全域性唯一
(2)由業務訊息傳送方生成,業務相關,對MQ透明
(3)由業務訊息消費方負責判重,以保證冪等
最常見的業務ID有:支付ID,訂單ID,帖子ID等。
具體到支付購卡場景,傳送方必須將支付ID放到訊息體中,消費方必須對同一個支付ID進行判重,保證購卡的冪等。
有了這個業務ID,才能夠保證下半場訊息消費業務方即使收到重複訊息,也只有1條訊息被消費,保證了冪等。
三、總結
MQ為了保證訊息必達,訊息上下半場均可能傳送重複訊息,如何保證訊息的冪等性呢?
上半場
MQ-client生成inner-msg-id,保證上半場冪等。
這個ID全域性唯一,業務無關,由MQ保證。
下半場
業務傳送方帶入biz-id,業務接收方去重保證冪等。
這個ID對單業務唯一,業務相關,對MQ透明。
結論:冪等性,不僅對MQ有要求,對業務上下游也有要求。
==【完】==
相關閱讀:
原文連結: