RocketMQ事務消息回查設計方案


用戶U1從A銀行系統轉賬給B銀行系統的用戶U2的處理過程如下:
第一步:A銀行系統生成一條轉賬消息,以事務消息的方式寫入RocketMQ,此時B銀行系統不可見這條消息(Prepare階段)

第二步:寫入MQ成功后,回調A銀行系統,對T1,T2表進行操作(很顯然需要是一個事務)
我們重點關注下T2表,這個表是用來干嘛的呢?每條轉賬消息都會在T2表中,該表有2個特殊的字段:status,updatetime。

第三步:完成第二步,接下來發送確認消息給MQ,如果這個確認消息發送成功,那么這條轉賬消息,將對B銀行系統可見。然后B銀行系統,會在一個事務中完成對t3,t5的操作。

如果發送確認消息給MQ失敗的處理思路:
首先,B銀行系統,有一個定時任務(比如說每隔1MIN執行一次),掃描表t5,取得一段時間內的數據,發送給A銀行系統。要知道t5中的數據,必然是A銀行系統成功處理並發送確認消息成功的轉賬數據。為什么要發送給A銀行系統呢,其實就是為了找到那些發送確認消息失敗的轉賬數據。那么怎么發給A銀行系統呢,這個方式比較多,可以考慮在來一個Topic,也可以考慮Netty等。發送給A銀行系統,其實就是為了更新t2表的status,updatetime。

這里有一個關鍵,如何“掃描表t5,取得一段時間內的數據”?這就是t4的作用,在t4中記錄一個time字段,每次定時任務啟動,先更新time(比如設定為當前系統時間,設置前的的時間為old),然后掃描出t5中大於這個old時間的轉賬數據,如此循環往復。

其次,A銀行系統,也有一個定時任務(可以根據業務消費能力定,可以大一些),掃描t2表(指定status及updatetime條件),將那些確認消息發送失敗的轉賬消息找出來,更新updatetime並發送給MQ。

這樣,我們並沒有改動RocketMQ 3.2.6的源碼,而是在外圍解決了事務回查!

其實到這里,你可以發現RocketMQ的一個特點,就是將生產者和MQ綁定,而不需要特別處理消費者,這是為什么呢?因為消息只要發往RocketMQ成功,那么就意味着成功,為什么這么說?

前面,我們說過,消費者端消費消息只會產生2種錯誤,第一:timeout,第二:exception。要知道RocketMQ對於超時,會不斷重試;對於消費異常,會根據消費端的返回碼,會有重試機制保證。也就是,RocketMQ一定會讓消息得到消費,如果消費有問題,只能是消費者的問題,而不會是RocketMQ的問題!

人工介入
可能有人又要說了,無論什么方案,發送端把消息成功放入了隊列,但消費端消費失敗怎么辦?

消費失敗了,重試,還一直失敗怎么辦?是不是要自動回滾整個流程?

答案是人工介入。從工程實踐角度講,這種整個流程自動回滾的代價是非常巨大的,不但實現復雜,還會引入新的問題。比如自動回滾失敗,又怎么處理?

對應這種極低概率的case,采取人工處理,會比實現一個高復雜的自動化回滾系統,更加可靠,也更加簡單。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM