這是小卷對(duì)分布式系統(tǒng)架構(gòu)學(xué)習(xí)的第13篇文章,今天學(xué)習(xí)面試中高頻問題:分布式事務(wù),為什么要用分布式事務(wù),分布式事務(wù)的實(shí)現(xiàn)方案有哪些,方案對(duì)比優(yōu)缺點(diǎn);
1.知識(shí)體系

1.為什么要用分布式事務(wù)
單體架構(gòu)時(shí),以本地事務(wù)為例,業(yè)務(wù)場(chǎng)景是下單場(chǎng)景,用戶下單、創(chuàng)建訂單、扣減庫(kù)存這些操作都可以在一個(gè)數(shù)據(jù)庫(kù)事務(wù)中完成。

而隨著業(yè)務(wù)的增長(zhǎng),系統(tǒng)轉(zhuǎn)變?yōu)榉植际较到y(tǒng),原有的單體架構(gòu)也拆分為多個(gè)微服務(wù)。下單場(chǎng)景需要在多個(gè)服務(wù)間操作,需要保證所有操作都能成功,保證整個(gè)下單流程的數(shù)據(jù)一致性,就需要用到分布式事務(wù)了

2.理論
- 分布式理論的CP -> 剛性事務(wù)
遵循ACID,對(duì)數(shù)據(jù)要求強(qiáng)一致性
- 分布式理論的AP+BASE -> 柔性事務(wù)
遵循BASE,允許一定時(shí)間內(nèi)不同節(jié)點(diǎn)的數(shù)據(jù)不一致,但要求最終一致。
這里重新復(fù)習(xí)一遍BASE理論是什么:
- 基本可用 Basically Available
- 軟狀態(tài) Soft State
- 最終一致性 Eventually Consistent
基本可用:是指系統(tǒng)出現(xiàn)未知故障時(shí),還是能用的;
軟狀態(tài):允許系統(tǒng)存在中間態(tài),即所有副本數(shù)據(jù)允許存在延遲;
最終一致性:存在軟狀態(tài),在一定時(shí)間后,所有副本數(shù)據(jù)保持一致,從而達(dá)到數(shù)據(jù)最終一致性;
3.剛性事務(wù)(CP模式)
剛性事務(wù)指的是強(qiáng)一致性,基礎(chǔ)是XA協(xié)議,XA協(xié)議是一個(gè)基于數(shù)據(jù)庫(kù)的分布式事務(wù)協(xié)議,其分為兩部分:事務(wù)管理器(Transaction Manager)*和*本地資源管理器(Resource Manager)**。事務(wù)管理器作為一個(gè)全局的調(diào)度者,負(fù)責(zé)對(duì)各個(gè)本地資源管理器統(tǒng)一號(hào)令提交或者回滾;
而2PC (兩階段提交)和3PC(三階段提交)都是由XA協(xié)議衍生出來的
3.1兩階段提交(2PC)
引入一個(gè)作為協(xié)調(diào)者(coordinator)的組件來統(tǒng)一掌控所有參與者(participant)的操作結(jié)果,并最終指示這些節(jié)點(diǎn)是否要把操作結(jié)果進(jìn)行真正的提交
2PC指的是 Prepare & Commit
第一階段:準(zhǔn)備階段:
- 協(xié)調(diào)者向所有參與者發(fā)送REQUEST-TO-PREPARE
- 當(dāng)參與者收到REQUEST-TO-PREPARE消息后,它向協(xié)調(diào)者發(fā)送消息PREPARE或者NO,表示事務(wù)是否準(zhǔn)備好;如果發(fā)送是NO,那么事務(wù)回滾;
第二階段:提交階段
- 協(xié)調(diào)者收集所有參與者的返回信息,如果所有參與者都回復(fù)PREPARED,那么協(xié)調(diào)者向所有參與者發(fā)送COMMIT消息,否則,協(xié)調(diào)者發(fā)送ABORT消息
- 參與者收到協(xié)調(diào)者發(fā)來的Commit消息或Abort消息,它將執(zhí)行提交或回滾,并向協(xié)調(diào)者發(fā)送DONE消息確認(rèn)

兩階段提交的缺點(diǎn):
- 網(wǎng)絡(luò)抖動(dòng)導(dǎo)致數(shù)據(jù)不一致:第二階段協(xié)調(diào)者向參與者發(fā)送commit命令后,如果發(fā)生網(wǎng)絡(luò)抖動(dòng),有一部分參與者未收到commit請(qǐng)求,則無法執(zhí)行事務(wù)提交,影響整個(gè)系統(tǒng)數(shù)據(jù)一致性;
- 超時(shí)導(dǎo)致的同步阻塞問題:2PC中所有參與者節(jié)點(diǎn)都是事務(wù)阻塞型,當(dāng)一個(gè)節(jié)點(diǎn)通信超時(shí),其余參與者都會(huì)被阻塞;
- 單點(diǎn)故障的風(fēng)險(xiǎn):整個(gè)過程嚴(yán)重依賴協(xié)調(diào)者,如果協(xié)調(diào)者故障,參與者處于鎖定資源的狀態(tài),無法完成事務(wù)commit的操作。即使重新選擇一個(gè)協(xié)調(diào)者,也無法解決因前一個(gè)協(xié)調(diào)者宕機(jī)導(dǎo)致的阻塞問題;
2PC只適用于兩個(gè)數(shù)據(jù)庫(kù)(數(shù)據(jù)庫(kù)實(shí)現(xiàn)了XA協(xié)議)之間使用,限制較大,兩個(gè)系統(tǒng)間無法使用
3.2 三階段提交(3PC)
在2PC的基礎(chǔ)上,第一階段和第二階段中插入一個(gè)準(zhǔn)備階段,同時(shí)在協(xié)調(diào)者和參與者中都引入超時(shí)機(jī)制,當(dāng)參與者為收到協(xié)調(diào)者發(fā)送的commit請(qǐng)求后,也會(huì)對(duì)本地事務(wù)commit,不會(huì)一直阻塞等待
過程如下:
- CanCommit:協(xié)調(diào)者向所有參與者發(fā)生Cancommit命令,算法可以執(zhí)行事務(wù)提交操作,如果都響應(yīng)YES,則下一階段;
- PreCommit:協(xié)調(diào)者向所有參與者發(fā)送Precommit命令,是否可以進(jìn)行事務(wù)預(yù)提交操作。參與者如果已執(zhí)行了事務(wù)操作,則回復(fù)YES,進(jìn)入下一階段。如果回復(fù)NO,或者協(xié)調(diào)者沒有收到參與者的回復(fù),協(xié)調(diào)者就向所有參與者發(fā)送Abort請(qǐng)求,執(zhí)行事務(wù)的中斷;
- DoCommit:所有參與者已經(jīng)回復(fù)YES,協(xié)調(diào)者發(fā)DoCommit命令正式提交事務(wù),如果協(xié)調(diào)者沒有收到參與者的ACK響應(yīng),則發(fā)Abort請(qǐng)求給所有參與者,中斷事務(wù)。

小結(jié):
2PC存在使用限制的問題,3PC存在數(shù)據(jù)不一致的問題,兩者在實(shí)際中很少使用;
4.柔性事務(wù)(AP +BASE 最終一致性)
柔性事務(wù)要求最終一致性,允許有中間態(tài),柔性事務(wù)可以分為:TCC、Saga、本地消息表、MQ事務(wù)方案、最大努力通知
4.1 TCC 補(bǔ)償事務(wù)
TCC(Try Confirm Cancel)補(bǔ)償事務(wù),與2PC不同的是,2PC是在DB層面,TCC是在應(yīng)用層面
三個(gè)操作步驟:
- Try階段:完成業(yè)務(wù)檢查,預(yù)留必須得業(yè)務(wù)資源;
- Confirm階段:執(zhí)行業(yè)務(wù)邏輯,只使用Try階段預(yù)留的業(yè)務(wù)資源。Confirm需滿足冪等性,保證一個(gè)分布式事務(wù)只成功一次;
- Cancel階段:取消操作,釋放Try階段預(yù)留的業(yè)務(wù)資源,需要冪等性;

4.2 Saga事務(wù)
Saga可以看做一個(gè)異步的、利用隊(duì)列實(shí)現(xiàn)的補(bǔ)償事務(wù)。
由一系列本地事務(wù)構(gòu)成,每個(gè)本地事務(wù)更新了數(shù)據(jù)庫(kù)后,會(huì)發(fā)布一條消息來觸發(fā)Saga中的下一個(gè)本地事務(wù)的執(zhí)行,如果某個(gè)本地事務(wù)失敗了,Saga會(huì)執(zhí)行這個(gè)失敗事務(wù)之前 已提交的所有事務(wù)的補(bǔ)償操作
Saga的實(shí)現(xiàn)最流行的兩種方式是:
- 基于事件的方式。這種方式?jīng)]有協(xié)調(diào)中心,整個(gè)模式的工作方式就像舞蹈一樣,各個(gè)舞蹈演員按照預(yù)先編排的動(dòng)作和走位各自表演,最終形成一只舞蹈。處于當(dāng)前Saga下的各個(gè)服務(wù),會(huì)產(chǎn)生某類事件,或者監(jiān)聽其它服務(wù)產(chǎn)生的事件并決定是否需要針對(duì)監(jiān)聽到的事件做出響應(yīng)。
- 基于命令的方式。這種方式的工作形式就像一只樂隊(duì),由一個(gè)指揮家(協(xié)調(diào)中心)來協(xié)調(diào)大家的工作。協(xié)調(diào)中心來告訴Saga的參與方應(yīng)該執(zhí)行哪一個(gè)本地事務(wù)
基于事件的方式
事務(wù)回滾:
- 基于事件的回滾,需要相關(guān)服務(wù)提供補(bǔ)償操作接口,某個(gè)節(jié)點(diǎn)發(fā)生無法執(zhí)行事件操作時(shí),需要發(fā)送事件通知,其他已執(zhí)行了事務(wù)的節(jié)點(diǎn)監(jiān)聽事件并回應(yīng)
- 優(yōu)點(diǎn):簡(jiǎn)單容易理解,適用于分布式事務(wù)只有2-4個(gè)步驟的場(chǎng)景。示例如:下單-扣款-庫(kù)存減貨-物流服務(wù)-訂單完成 這樣簡(jiǎn)單的場(chǎng)景
- 缺點(diǎn):參與業(yè)務(wù)方多時(shí),會(huì)出現(xiàn)很多問題
4.3本地消息表
本地消息表的核心是將分布式事務(wù)拆成本地事務(wù)進(jìn)行處理,最初是由eBay提出的
下面以一個(gè)訂單場(chǎng)景具體說明本地消息表的實(shí)現(xiàn)
例如,可以在訂單庫(kù)新增一個(gè)消息表,將新增訂單和新增消息放到一個(gè)事務(wù)里完成,然后通過輪詢的方式去查詢消息表,將消息推送到 MQ,庫(kù)存服務(wù)去消費(fèi) MQ。

執(zhí)行流程為:
- 訂單服務(wù),在一個(gè)事務(wù)里增加一個(gè)訂單和一條消息,并提交
- 訂單服務(wù)通過輪詢的方式,查出未同步的消息,發(fā)到MQ,從設(shè)置失敗重試機(jī)制;
- 庫(kù)存服務(wù),負(fù)責(zé)接收MQ消息,進(jìn)行消費(fèi)修改庫(kù)存,由消費(fèi)方保證冪等性;
- 庫(kù)存服務(wù)修改成功后,調(diào)RPC接口修改訂單服務(wù)的消息表狀態(tài);
- 修改失敗,等待重試
優(yōu)點(diǎn):方案輕量,消息可靠性不依賴消息中間件;
缺點(diǎn):與業(yè)務(wù)強(qiáng)耦合,不可公用,消息數(shù)據(jù)與業(yè)務(wù)庫(kù)同庫(kù),占資源;
4.4 MQ消息事務(wù)
MQ事務(wù)是對(duì)本地消息表的封裝,將本地消息表存到MQ內(nèi)部了,而不是業(yè)務(wù)數(shù)據(jù)庫(kù)
將兩個(gè)事務(wù)通過消息隊(duì)列進(jìn)行異步解耦,加上重試機(jī)制保證最終一致性

發(fā)消息邏輯如下:

- 發(fā)送方向MQ server端發(fā)送half消息;
- MQ server將消息持久化后,發(fā)ACK給發(fā)送方
- 發(fā)送方開始執(zhí)行本地事務(wù)
- 執(zhí)行完成后,向MQ server提交二次確認(rèn)
- MQ server收到commit狀態(tài)將半消息標(biāo)記為可投遞,訂閱方將收到消息;MQ server如收到rollback狀態(tài)則刪除半消息,訂閱方收不到消息;
缺點(diǎn):一次消息發(fā)送需要兩次網(wǎng)絡(luò)請(qǐng)求(half + commit/rolllback消息)
4.5 最大努力通知
也成為定期校對(duì),是對(duì)MQ事務(wù)的進(jìn)一步優(yōu)化。
事務(wù)發(fā)起方增加了消息校對(duì)接口,也就是查詢接口,事務(wù)接收方可以自行調(diào)用接口主動(dòng)獲取操作結(jié)果
邏輯如下:
事務(wù)主動(dòng)方盡最大努力(重試,輪詢....)將事務(wù)發(fā)送給事務(wù)接收方,但是仍然存在消息接收不到,此時(shí)需要事務(wù)被動(dòng)方主動(dòng)調(diào)用事務(wù)主動(dòng)方的消息校對(duì)接口查詢業(yè)務(wù)消息并消費(fèi),這種通知的可靠性是由事務(wù)被動(dòng)方保證的

適用場(chǎng)景:
業(yè)務(wù)通知類型的場(chǎng)景,如微信交易的結(jié)果,就是通過最大努力通知方式通知各個(gè)商戶,既有回調(diào)通知,也有交易查詢接口
5. Seata框架
開源的分布式事務(wù)解決方案,提供了AT、TCC、SAGA、XA事務(wù)模式,不需要自己手動(dòng)實(shí)現(xiàn)分布式事務(wù),直接使用框架就行
有以下幾個(gè)角色:
- TC (Transaction Coordinator) - 事務(wù)協(xié)調(diào)者: 維護(hù)全局和分支事務(wù)的狀態(tài),驅(qū)動(dòng)全局事務(wù)提交或回滾。
- TM (Transaction Manager) - 事務(wù)管理器: 定義全局事務(wù)的范圍:開始全局事務(wù)、提交或回滾全局事務(wù)。
- RM (Resource Manager) - 資源管理器: 管理分支事務(wù)處理的資源,與TC交談以注冊(cè)分支事務(wù)和報(bào)告分支事務(wù)的狀態(tài),并驅(qū)動(dòng)分支事務(wù)提交或回滾。
