分布式事務概念
在微服務架構下,一個大的操作往往由不同的小操作組成,並且這些小操作分布在不同的服務器上,對應不同的數據庫,分布式事務需要保證這些小操作要么全部成功要么全部失敗,即保證數據一致性。
例如一個支付業務:

在某些業務場景下,用戶發起支付申請,只要申請成功,就可以做其他事情。
正常流程:
- 系統接受到申請后,支付申請服務經過一些業務校驗,先落支付申請庫
- 再將消息發送至MQ
- 支付交易服務監聽到MQ消息進行進一步的處理落庫。
但此時也有一些新的問題出現:
- 若支付申請服務完成邏輯后,在投遞消息到MQ中間件的過程中由於網絡抖動等原因,沒有投遞到MQ中導致消息丟失了怎么辦?
- MQ接收到消息后,由於內部原因導致消息丟失了怎么辦?
- 支付交易服務在監聽消息的過程中,由於網絡原因沒有接收到消息或消費過程中遇到異常,此時也會導致消息丟失,怎么辦?
- 由於MQ組件問題,導致支付交易服務重復消費怎么辦?
針對前三種問題,都是消息丟失導致的,可以采用本地消息表+定時任務來解決。
針對第四種問題,是因為重復消費導致的,就需要支付交易服務做好冪等防重。
增加本地消息表+定時任務
此時數據流程如下:

正向流程:
- 系統接受到申請后,在同一本地事務寫入本地消息表和業務表,本地消息表狀態為處理中,再發送消息到MQ
- 支付交易服務監聽到消息后,進行一些邏輯之后,將結果發送至MQ
- 支付申請監聽到處理結果,更新本地消息表的狀態,處理結束
補償措施:
- 假如消息丟失,還有定時任務定時掃描本地消息表中狀態為處理中的數據,進行下發,后續處理和正向流程的2、3一致
特點
- 最大努力通知
- 最終一致性
注意
- 真實業務處理的狀態可能會有多種,因此需要明確哪種狀態需要定時任務補償
- 假如某條單據一直無法處理結束,定時任務也不能無限制下發,所以本地消息表需要增加輪次的概念,重試多少次后告警,人工介入處理
- 因為MQ和定時任務的存在,難免會出現重復請求,因此下游要做好冪等防重,否則會出大問題
