其他方案
1.事務狀態表+調??重試+接收?冪等
介紹
調??維護?張事務狀態表(或者說事務?志、?志流?),在每次調?之前,落盤?條事務流?,?成?個全局的事務ID
事務開始之前的狀態是Begin,全部結束之后的狀態是End。如果某個事務?直停留在Begin狀態,則說明該事務沒有執?完畢
然后有?個后臺任務,掃描狀態表,在過了某段時間后(假設1次事務執?成功通常最多花費30s),狀態沒有變為最終的狀態,說明這條事務沒有執?成功。于是重新調?系統的接口。保證這條流?的最終狀態是End狀態
事務狀態表
補充說明
- 冪等問題:系統調用方和被調用方根據全局的事務ID做冪等操作,所以即使重復調?也沒有關系
- 如果后臺任務重試多次仍然不能成功,要為狀態表加?個Error狀態,通過??介??預
- 對于同步調?,調??調?A或B失敗的時候,可以重試三次。如果重試三次還不成功,則放棄操作,再交由后臺任務后續處理
2.對賬
介紹
所有的“過程”都必然產?“結果”,過程是我們所說的“事務”,結果就是業務數據。?個過程如果部分執?成功、部分執?失敗,則意味著結果是不完整的。從結果也可以反推出過程出了問題,從?對數據進?修補,這就是“對賬”的思路
分類
- 全量對賬:?如每天晚上運作?個定時任務,對比兩個數據庫
- 增量對賬:可以是?個定時任務,基于數據庫的更新時間;也可以基于消息中間件,每?次業務操作都拋出?個消息到消息中間件,然后由?個消費者消費這條消息,對兩個數據庫中的數據進??對(當然,消息可能丟失,?法百分之百地保證,還是需要全量對賬來兜底)
例子
案例1
電商?站的訂單履約系統。?張訂單從“已?付”,到“下發給倉庫”,到“出倉完成”。假定從“已?付”到“下發給倉庫”最多?1個?時;從“下發給倉庫”到“出倉完成”最多?8個?時。意味著只要發現1個訂單的狀態過了1個?時之后還處于“已?付”狀態,就認為訂單下發沒有成功,需要重新下發,也就是“重試”。同樣,只要發現訂單過了8個?時還未出倉,這時可能會發出報警,倉庫的作業系統是否出了問題……諸如此類
案例2
微博的關注關系。需要存兩張表,?張是關注表,?張是粉絲表,這兩張表各?都是分庫分表的。假設A關注了B,需要先以A為主鍵進?分庫,存?關注表;再以B為主鍵進?分庫,存?粉絲表。也就是說,?次業務操作,要向兩個數據庫中寫?兩條數據,如何保證原?性?
案例3
電商的訂單系統也是分庫分表的。訂單通常有兩個常?的查詢維度,?個是買家,?個是賣家。如果按買家分庫,按賣家查詢就不好做;如果按賣家分庫,按買家查詢就不好做。這種通常會把訂單數據冗余?份,按買家進?分庫分表存?份,按賣家再分庫分表存?份。和案例2存在同樣的問題:?個訂單要向兩個數據庫中寫?兩條數據,如何保證原?性?
案例2和3的解決思路
如果把案例 2、案例 3 的問題看作為?個分布式事務的話,可以?對賬解決
因為兩個庫的數據是冗余的,可以先保證?個庫的數據是準確的,以該庫為基準校對另外?個庫
總結
對賬的關鍵是要找出“數據背后的數學規律”。有些規律?較直接,誰都能看出來,?如案例2、案例3的冗余數據庫;有些規律隱含?些,?如案例1的訂單履約的狀態。找到了規律就可以基于規律進?數據的?對,發現問題,然后補償
3.弱?致性+基于狀態的補償
場景
需求解析
對于該需求,有?個關鍵特性:對于電商的購物來講,允許少賣,但不能超賣。?如有100件東西,賣給99個?,有1件沒有賣出去,這是可以接受的;但如果賣給了101個?,其中1個?拿不到貨,平臺違約,這就不能接受。?該處就利?了這個特性
流程
- 提交訂單成功,扣庫存成功,返回成功
- 提交訂單成功,扣庫存失敗,返回失敗,調??重試(此處可能會多扣庫存)
- 提交訂單失敗,不再扣庫存,調??重試
解決
只要最終保證庫存可以多扣,不能少扣即可
但是,庫存多扣了,數據不?致,怎么補償呢?
庫存每扣?次,都會?成?條流?記錄。這條記錄的初始狀態是“占?”,等訂單?付成功后,會把狀態改成“釋放”
對于那些過了很長時間?直是占?,?不釋放的庫存,要么是因為前?多扣造成的,要么是因為?戶下了單但沒有?付
通過?對,得到庫存系統的“占?又沒有釋放的庫存流?”與訂單系統的未?付的訂單,就可以回收這些庫存,同時把對應的訂單取消。類似12306?站,過?定時間不?付,訂單會取消,將庫存釋放
4.重試+回滾+報警+??修復
先扣庫存,后創建訂單。不做狀態補償,為庫存系統提供?個回滾接口。創建訂單如果失敗了,先重試。如果重試還不成功,則回滾庫存的扣減。如回滾也失敗,則發報警,進????預修復
總之,根據業務邏輯,通過三次重試或回滾的?法,最?限度地保證?致。實在不?致,就發報警,讓???預。只要?志流?記錄得完整,??肯定可以修復!通常只要業務邏輯本?沒問題,重試、回滾之后還失敗的概率會?較低,所以這種辦法雖然丑陋,但很實?