問題思考
訂單系統和積分系統、財務記賬系統在不同的系統中,如果訂單操作成功,積分系統或財務系統沒有對應的記錄,就會造成數據不一致的情況,在這種背景下就需要有一套方案解決不一致的情況.
方案圖如下(龍果學院方案圖):
流程: 1預發消息 2dubbo返回 3確認並發送 4發送消息 5監聽接收消息 6ACK確認已收到 7確認該條事務已處理成功;
在這個案例中只列舉兩個系統之間的分布式事務,可以簡單的理解為訂單系統和記賬系統
示例圖解釋
- 藍色虛線塊:事務主動發起方,整個流程的起源,可以理解為在訂單系統用戶支付環節
- 紫色虛線塊:消息服務子系統,將消息存入數據庫,保證消息可靠性
- 綠色虛線塊:事務被調用方,可以理解為記賬系統對這次支付操作進行記賬
- 消息狀態確認子系統:確認消息被成功消費,如果沒有成功消費則作為補償需要重新發送
- 消息恢復子系統:消息服務子系統的消息在多次發送之后仍沒有被 “被動放應用系統” 確認消費則需要掛起,消息恢復子系統的任務就是讓“消息服務子系統”的消息重新激活並發送,確保 “被動方應用系統”重新上線后可以消費掉此消息
調用流程與容錯處理

異常流程:
- 若是1或2失敗,則整個事務失敗
- 若是3失敗,則“消息狀態子系統”掃描“消息服務子系統”中的存儲在表中的預處理數據,並反向查詢“主動應用系統”,如果“主動應用系統”查詢到的訂單狀態是已處理完成,則調用“消息服務子系統”的儲存的消息狀態修改為已發送待消費接口並調用“消息服務子系統”的發送消息接口。
- 若是4失敗,意味着“被動方應用系統”無法消費消息,那么必然不會執行7,此時就需要“消息恢復子系統”,定期檢查“消息服務子系統”中的未確認已過期消息,並由“消息恢復子系統”重新發送出去,若消息已發出並走正常流程,則會被7確認已處理並消費
- 若是5失敗,則和異常流程c一樣,由“消息恢復子系統”處理
- 若是6失敗,而7已經成功確認,則此條消息就會被重復消費,那么就體現出冪等的重要性,當“被動方應用系統”消費消息時需要做冪等處理,避免重復操作
- 若是7失敗,此時的影響就是“被動方應用系統”成功消費並處理成功,但是未通知到“消息服務子系統”,那么當“消息恢復子系統”子系統重新發送消息時,需要做冪等處理,並重新走7流程;
拓展
- 圖中紫色部分 消息服務子系統、消息確認子系統、消息恢復子系統設置成3個系統的原因是為了解耦
- 消息服務子系統具備消息存儲和消息發送功能, 主要體現在能力的提供,可作為公用服務
- 消息恢復子系統和消息確認子系統則與業務密切相關, 需要根據消息查詢具體業務是否處理成功,所以獨立出來
- 現實中業務量不大的情況下, 消息確認服務以模塊的方式集成到調用業務系統中, 消息恢復子系統集成到消息子系統中, 從而只需要部署一個服務即可
- 消息服務子系統中可以使用redis分布式鎖提升性能(重復操作時)
總結
- 分布式事務中冪等判斷非常重要
- 網絡是不可靠的,任何流程都有可能失敗,需要多種失敗補償策略
- 與基於DAO層分布式事務相比較; 優點是可控性強和可視化,代碼解耦,削峰填谷; 缺點是只能用於通知型事務,時效性 不足, 編碼量較多, 有代碼侵入.