一文详解,RocketMQ事务消息
在RocketMQ中有一個非常有用的功能,就是事務消息功能,事務消息機制,可以讓我們確保發送的消息一定能寫進MQ里,絕不會丟失掉。
MQ事務消息機制還是挺有用的,在業內還是比較常見的,所以今天我們就來分析下RocketMQ事務消息的原理。
1、發送half消息到MQ去,試探MQ是否正常
使用RocketMQ的事務消息,我們首先要發送一條half消息到MQ中去,這個half你可以理解為一個試探消息,這個時候消費者系統是看不見這個half消息的。
然后生產者就等待接收這個half消息寫入成功的響應通知,我們看圖1:
圖1?生產者發送half消息
如果half消息寫入失敗了怎么辦?
假如你MQ掛了,或者網絡故障了,導致你half消息沒有發送成功。這個時候,后續業務邏輯就可以不執行了。
half消息成功之后,我們就應該執行相應的業務邏輯,比如對數據庫執行一些增刪改操作。
圖2?half消息成功,生產者執行本地業務邏輯
2、生產者本地事務執行失敗了怎么辦?
比如生產者增刪改數據庫的時候失敗了,這個時候就要發送一條rollback請求給MQ,就是告訴MQ把我之前發給你的half消息給刪除了,因為我自己出現問題了,沒法執行后續的業務邏輯。
圖3?生產者執行本地事務失敗
請求MQ刪除half消息后,生產者本地事務就回滾了,不執行后邊的流程了。
3、生產者完成了本地事務
如果生產者完成了本地事務,此時你就可以發送一個commit消息給MQ要求MQ對之前的half消息進行commit。
圖4?生產者發送commmit消息
消息是half的時候,消費者是看不到的,現在MQ收到了commit消息,就可以執行后邊的流程了。
4、假如half消息發送成功了,生產者沒收到響應怎么辦?
MQ事務消息流程就是上面的,但是我們來進行比較嚴謹的分析,如果我們把half消息發送給MQ了,MQ給保存下來了,但是MQ返回給我們的響應生產者沒收到,會怎么樣?
這時候,生產者會誤以為發送到MQ的half消息失敗了,就不會執行后邊的流程。
但MQ已經保存下來了一條half消息,這個消息怎么處理?
其實RocketMQ這里有一個補償機制,他會去掃描自己處于half狀態的消息,如果我們一直沒有對這個消息執行commit或rollback操作,超過了一定的時間,他就會回調你的訂單系統的一個接口,看看你這個消息什么情況,你生產者到底是打算commit這個消息,還是打算rollback這個消息?
圖5 消息補償機制
生產者收到MQ的回調請求,就會去查看下本地事務執行的結果,比如查詢數據庫數據狀態。
5、rollback或者commit發送失敗了呢,怎么辦?
假如生產者收到half消息發送成功的消息了, 同時嘗試執行自己本地事務,然后也執行了rollback或者commit,結果因為網絡故障或其他原因,導致rollback或者commit請求發送失敗了,怎么辦?
這個時候MQ中的消息一直處于half狀態,過了一定的超時時間就會發現這個half消息有問題,會回調你的生產者系統接口。
此時你要判斷一下,如果本地事務執行成功了,那你就得再次執行commit請求,反之則再次執行rollback請求。
這個MQ的回調就是一個補償機制,如果你的half消息響應沒收到,或者rollback、commit請求沒發送成功,MQ都會來找你詢問后續如何處理。
再假設一種場景,如果生產者系統收到了half消息寫入成功的響應了,同時嘗試執行自己本地事務,然后根據失敗或者成功去執行rollback或者commit請求,發送給MQ了。很不巧,mq在這個時候掛掉了,導致rollback或者commit請求發送失敗,怎么辦?
這種情況的話,那就等MQ自己重啟了,重啟之后他會掃描half消息,然后還是通過上面說到的補償機制,去回調你的接口。
總結:
MQ事務機制都在那些環節保證了數據一定可以投遞到MQ?
如果你的MQ有問題或者網絡有問題,half消息根本發不出去,此時half消息肯定是失敗的,那么生產者系統就不會執行后續流程了!
如果要是half消息發送出去了,但是half消息的響應都沒收到,然后執行了回滾操作,那MQ會有補償機制來回調找你詢問要commit還是rollback,此時你選擇rollback刪除消息就可以了,不會執行后續流程!
如果要是生產者系統收到half消息了,結果自己更新數據庫失敗了,那么他也會進行回滾,不會執行后續流程了!
如果要是生產者系統收到half消息了,然后還更新自己數據庫成功了,訂單狀態是“已完成”了,此時就必然會發送commit請求給MQ,一旦消息commit了,那么必然保證消費者系統可以收到這個消息!
即使你commit請求發送失敗了,MQ也會有補償機制,回調你接口讓你判斷是否重新發送commit請求。
總之,就是你的生產者系統只要成功了,那么必然要保證MQ里的消息是commit了可以讓消費者系統看到他!
所以大家可以梳理下上面的流程,通過這套事務消息的機制,就可以保證我們的生產者系統一旦成功執行了數據庫操作,生產者系統到MQ之間的消息傳輸是不會有丟失的問題了!
關于RocketMQ事務消息的代碼,大家可以參考官方example。
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
總結
以上是生活随笔為你收集整理的一文详解,RocketMQ事务消息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot 如何进行对象复制,
- 下一篇: 最近,我和隐私计算干上了。