簡單聊聊事務補償機制


假設有如下的業務流程,用戶1給用戶2轉賬100元:

 

 轉賬服務需要執行如下操作:

第1步. 在數據庫連接1上執行:update 用戶表 set (用戶1的余額) = (用戶1的余額)- 100;

第2步. 在數據庫連接2上執行:update 用戶表 set (用戶2的余額) = (用戶2的余額)+ 100;

可能的問題:

1:第1步操作過程中,數據庫1掛了,轉賬服務無法得知對用戶1的扣款操作是否成功;

2:第1步操作成功,第2步操作失敗,轉賬服務回滾第1步的操作時,數據庫1掛了;

3:第1步操作成功,第2步操作過程中,數據庫2掛了,轉賬服務無法得知是否成功給用戶2加了錢;

 

基於上面的問題,產生了如下的數據庫設計:

轉賬流程變成了如下步驟:

第1步:

    轉賬服務生成一個事務號,全局唯一;

第2步:轉賬服務在數據庫1上執行事務:

    開始事務:

        update 用戶表 set (用戶1的余額) = (用戶1的余額)- 100;

        insert 事務表 (事務號,成功)

    結束事務:

第3步:轉賬服務在數據庫2上執行事務:

    開始事務:

        update 用戶表 set (用戶2的余額) = (用戶2的余額)+ 100;

        insert 事務表 (事務號,成功)

    結束事務:

 

這樣做的好處

    當操作用戶1的賬戶失敗時,轉賬服務可以通過再次查詢數據庫1的事務表來判斷操作是否成功;

    當操作用戶2的賬戶失敗時,轉賬服務可以通過再次查詢數據庫2的事務表來判斷操作是否成功;

接下來的問題:

    當轉賬服務更新用戶1的賬戶成功后,接下來轉賬服務更新用戶2的賬戶之前,轉賬服務自己掛了;

    這時,用戶1被扣了100,但是用戶2沒多出來100,數據不一致;

 

新的數據庫設計產生了,如下:

    

 

接下來的操作步驟變成了這樣:

轉賬服務的操作:

    第1步:生成全局唯一事務號;生成事務號對應的時間戳;

    第2步:在回滾庫的日志表中插入---“事務號開始”的操作;

    第3步:在回滾庫的日志表插入---“扣除用戶1的賬戶100元“的操作;

    第4步:在數據庫1上執行事務:

        開始事務:

            update 用戶表 set (用戶1的余額) = (用戶1的余額)- 100;

            insert 事務表 (事務號,成功)

        結束事務:

    第5步:在回滾庫的日志表插入---“增加用戶2的賬戶100元”的操作;

    第6步:在數據庫2上執行事務:

        開始事務:

            update 用戶表 set (用戶2的余額) = (用戶2的余額)+ 100;

            insert 事務表 (事務號,成功)

        結束事務:


    第7步:在回滾庫的日志表插入---“事務號結束”的操作;

 

回滾服務的操作:

    假設轉賬超時時間是1小時;

    定期檢查回滾庫中的回滾日志表;

    如果事務號對應結束,則忽略;

    如果事務號沒有結束,但是事務沒超時,也忽略;

    如果事務號沒有結束,事務超時,則按照回滾日志,反向操作,對事務進行補償,補償步驟如下:

        第1步:對用戶2進行事務補償,檢查數據庫2的用戶2的事務是否成功;

        第2步:如果成功,則認為事務完成,在事務回滾日志表中將這次事務標識為成功;並跳到“結束步驟”;

        第3步:對用戶1進行事務補償,檢查數據庫1的用戶1的事務是否成功;

        第4步:如果成功,則執行如下事務:

            開始事務

                update 用戶表 set (用戶1的余額) = (用戶1的余額)+ 100;

                update 事務表 (事務號,回滾成功);

            結束事務

        第5步:在事務回滾日志表將這次事務標識為成功;

        結束步驟

 

 結束哈;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM