基於訊息佇列實現分散式事務
阿新 • • 發佈:2019-12-31
基於訊息佇列實現分散式事務
場景:
訂單系統產生訂單,購物車系統減購物車中的商。
實現思路 :
- 訂單系統在訊息佇列上開啟一個事務(沒有建立訂單)。
- 訂單系統給訊息伺服器傳送一個“半訊息”,這個半訊息不是說訊息內容不完整,它包含的內容就是完整的訊息內容,半訊息和普通訊息的唯一區別是,在事務提交之前,對於消費者來說,這個訊息是不可見的。
- 半訊息傳送成功後,訂單系統就可以執行本地事務了,在訂單庫中建立一條訂單記錄,並提交訂單庫的資料庫事務。
- 然後根據本地事務的執行結果決定提交或者回滾事務訊息。如果訂單建立成功,那就提交事務訊息,購物車系統就可以消費到這條訊息繼續後續的流程。如果訂單建立失敗,那就回滾事務訊息,購物車系統就不會收到這條訊息。
橙色和綠色分別是兩個事務。
問題:
步驟4事務提交失敗;這時候訂單系統本地事務已提交爾購物車系統沒有收到訊息,造成資料不一致。
如何解決訊息佇列事務提交過程出現的異常:
kafka會直接丟擲異常使用者自行處理;
在RocketMQ中的事務實現中,增加了事務反查的機制來解決事務訊息提交失敗的問題,RocketMQ的Broker沒有收到提交或者回滾的請求,Broker會定期去producer上反查這個事務對應的本地事務的狀態,然後根據反查結果決定提交或者回滾這個事務。
為了支援事務反查機制,我們的業務程式碼需要實現一個反查本地事務狀態的介面告知RocketMQ本地事務是成功還是失敗。
本例中的反查邏輯很簡單隻需根據訊息中的訂單ID,在訂單庫中查詢訂單是否存在即可。
能不能在訂單建立完成後再向訊息佇列傳送訂單資料?這樣不用考慮訂單建立失敗而傳送訊息的情況了
考慮這樣一種情況:訂單建立成功了,還沒來得及發訊息,這個節點突然斷電了。
還有一種情況訂單建立成功,減購物車(後續操作)失敗的話要寫實物補償把建立的訂單刪掉。
能不能這樣:
1.開啟本地事務建立訂單,2.發訊息,3.根據發訊息是否成功來決定提交還是回滾本地事務。這樣不需要事務訊息也能解決這個場景的問題了?
如果本地事務提交失敗已傳送的訊息無法撤回,會導致資料不一致。
小結
不論是訊息佇列事務還是非同步事務都遵循事務的四大特性:原子性,一致性,隔離性,永續性。
更多實現分散式事務的方法: blog.csdn.net/ityqing/art…
**** 碼字不易如果對你有幫助請給個關注****
**** 愛技術愛生活 QQ群: 894109590****