提起分布式系統,就會(huì )涉及分布式事務(wù),本文就以金融項目的轉賬業(yè)務(wù)為例,分析各種業(yè)務(wù)場(chǎng)景下的轉賬業(yè)務(wù)的事物問(wèn)題。
一、業(yè)務(wù)場(chǎng)景
以工商銀行轉賬業(yè)務(wù)為例,那么項目的分布式架構大致如下,一個(gè)銀行的一個(gè)支行部署一個(gè)節點(diǎn),那么相同節點(diǎn)之間的業(yè)務(wù)就是本地事務(wù)、不同節點(diǎn)之間的就是分布式事務(wù)
轉賬業(yè)務(wù)包括以下三種情況
支行內轉賬:同為工行的相同支行內轉賬(本地事務(wù))
行內轉賬:同為工行的非同支行內轉賬 (分布式事務(wù))
跨行轉賬:和其他銀行的系統進(jìn)行轉賬 (分布式事務(wù))
1.1、支行內轉賬業(yè)務(wù)
如用戶(hù)A和用戶(hù)B都是工行-杭州支行的用戶(hù),A向B轉賬10000元,那么就需要保證事務(wù),從而達到A的賬戶(hù)-10000,而B(niǎo)的賬戶(hù)+10000的效果
由于是本地事務(wù),所以A賬戶(hù)的扣減和B賬戶(hù)的增加就可以放在一個(gè)事務(wù)中實(shí)現,基本上沒(méi)有太大的問(wèn)題,不管哪一步異常了都可以實(shí)現事務(wù)回滾。
1.2、行內轉賬
如用戶(hù)A是杭州支行,用戶(hù)B是北京支行,A向B轉賬10000元,那么雖然都是工行用戶(hù),但是是分布式部署的,就會(huì )涉及到跨庫的分布式事務(wù)問(wèn)題,一般解決方案有同步和異步兩種方式:
同步方式可以如下:
1、創(chuàng )建轉賬訂單,訂單狀態(tài)為待成功
2、用戶(hù)A扣減10000元
3、發(fā)起轉賬請求到北京支行
4、北京支行創(chuàng )建轉賬訂單,訂單狀態(tài)為待成功
5、用戶(hù)B增加10000元
6、北京支行訂單狀態(tài)改為成功并返回結果
7、杭州支行接收響應結果,如果為成功則提交事務(wù)表示轉賬成功,如果為失敗則更新訂單狀態(tài)為轉賬失敗
8、定時(shí)任務(wù)根據查詢(xún)轉賬失敗訂單在北京支行的訂單訂單狀態(tài),如果失敗,則回滾轉賬事務(wù);如果成功則提交事務(wù)
異步方式如下:
1、創(chuàng )建轉賬訂單
2、用戶(hù)A凍結10000元
3、提交事務(wù)
4、異步發(fā)起轉賬請求,判斷結果
結果可以為:
1、轉賬成功:確認成功
2、轉賬失?。捍_認失敗
3、請求異常:結果不確認
對于結果不確定的情況就采用:查詢(xún)的方式查詢(xún)結果,查詢(xún)結果還是不確定的話(huà)
就采用定時(shí)任務(wù)查詢(xún)異常訂單查詢(xún)
1.3、跨行轉賬
如用戶(hù)A是工行用戶(hù),用戶(hù)B是建行用戶(hù),A向B轉賬10000元,這里兩個(gè)用戶(hù)不是同一個(gè)行的用戶(hù),基本上就不會(huì )再采用同步的方式進(jìn)行轉賬了。
異步方式如下:
1、創(chuàng )建轉賬訂單,訂單狀態(tài)為待成功
2、用戶(hù)A凍結10000元
3、提交事務(wù)
這里需要保證的是用戶(hù)資金和訂單狀態(tài)的事務(wù)
異步發(fā)送http請求到其他行進(jìn)行轉賬業(yè)務(wù),
結果可以為:
1、轉賬成功:確認成功
2、轉賬失?。捍_認失敗
3、請求異常:結果不確認
對于結果不確定的情況就采用:查詢(xún)的方式查詢(xún)結果,查詢(xún)結果還是不確定的話(huà)
就采用定時(shí)任務(wù)查詢(xún)異常訂單查詢(xún)
金融項目一般不會(huì )太重視轉賬的實(shí)時(shí)性,而是重視轉賬的一致性,比較涉及到的是金錢(qián),所以必須要確保轉賬的事務(wù)性。
總體來(lái)說(shuō),解決轉賬的分布式事務(wù)還是以異步為主,采用的是最終一致性來(lái)解決分布式事務(wù)問(wèn)題。大致流程如下:
1、事務(wù)1執行事務(wù),并創(chuàng )建訂單,確保訂單和金額變得的一致性
2、異步發(fā)起轉賬請求
3、接收異步回調或同步響應
4、如果是成功則更新訂單狀態(tài)和金額、如果是失敗則回滾、如果是不確定則通過(guò)查詢(xún)的方式來(lái)確認訂單的結果
5、根據訂單的最終結果來(lái)更新數據
二、其他分布式事務(wù)解決方案
2.1、基于XA的二階段提交協(xié)議
基于二階段提交的方案主要是將事務(wù)分成了兩個(gè)階段,一個(gè)是事務(wù)準備階段,一個(gè)是事務(wù)提交階段,并且需要一個(gè)事務(wù)管理者的角色,也就是事務(wù)管理器
第一階段:
1、事務(wù)管理器通知所有參與事務(wù)的各個(gè)本地資源管理器,通知他們準備事務(wù)
2、各個(gè)本地資源管理器進(jìn)行事務(wù)準備,寫(xiě)好事務(wù)日志并執行事務(wù),但是不提交,然后將本地事務(wù)執行的結果上報給事務(wù)管理器
第二階段:
1、事務(wù)管理器接收各個(gè)本地資源管理器執行的事務(wù)結果,如果全部成功則表示事務(wù)成功,需要提交;如果有一個(gè)失敗則表示事務(wù)失敗,需要回滾
2、事務(wù)管理器向各個(gè)資源管理器發(fā)生提交或回滾請求,各個(gè)資源管理器分別進(jìn)行提交或回滾(提交或回滾的耗時(shí)很短,失敗的概率相對很低)
2.2、TCC方案
TCC方案是將事務(wù)分成了三個(gè)階段,分別是try、commit、callback階段。
事務(wù)開(kāi)始時(shí),業(yè)務(wù)應用會(huì )向事務(wù)協(xié)調器注冊啟動(dòng)事務(wù)。之后業(yè)務(wù)應用會(huì )調用所有服務(wù)的try接口,完成一階段準備。之后事務(wù)協(xié)調器會(huì )根據try接口返回情況,決定調用confirm接口或者cancel接口。如果接口調用失敗,會(huì )進(jìn)行重試。
TCC方案讓?xiě)米约憾x數據庫操作的粒度,使得降低鎖沖突、提高吞吐量成為可能。 當然TCC方案也有不足之處,集中表現在以下兩個(gè)方面:
- 對應用的侵入性強。業(yè)務(wù)邏輯的每個(gè)分支都需要實(shí)現try、confirm、cancel三個(gè)操作,應用侵入性較強,改造成本高。
- 實(shí)現難度較大。需要按照網(wǎng)絡(luò )狀態(tài)、系統故障等不同的失敗原因實(shí)現不同的回滾策略。為了滿(mǎn)足一致性的要求,confirm和cancel接口必須實(shí)現冪等。
上述原因導致TCC方案大多被研發(fā)實(shí)力較強、有迫切需求的大公司所采用。微服務(wù)倡導服務(wù)的輕量化、易部署,而TCC方案中很多事務(wù)的處理邏輯需要應用自己編碼實(shí)現,復雜且開(kāi)發(fā)量大。
2.3、基于MQ的最終一致性
基于MQ的一致性相當于是異步實(shí)現的分布式事務(wù),將事務(wù)分成了兩個(gè)不關(guān)聯(lián)的本地事務(wù),基于MQ進(jìn)行同步,根據最終結果實(shí)現一致性從而達到分布式事務(wù)
2.4、基于fescar實(shí)現的分布式事務(wù)
XA的第一階段是執行sql,但是不提交,第二階段一起提交 (會(huì )導致鎖的時(shí)間是整個(gè)事務(wù)的時(shí)間)
Fescar的第一階段是各個(gè)分支事務(wù)執行并提交事務(wù),只是在提交之前持久化了回滾日志(undo log),第二階段如果是提交的話(huà)就只需要刪除持久化日志即可;否則才需要執行回滾操作
主要是對XA的優(yōu)化,第一階段的區別