這是小卷對分布式系統(tǒng)架構(gòu)學(xué)習(xí)的第13篇文章苍鲜,今天學(xué)習(xí)面試中高頻問題:分布式事務(wù),為什么要用分布式事務(wù),分布式事務(wù)的實(shí)現(xiàn)方案有哪些事甜,方案對比優(yōu)缺點(diǎn)允蜈;
1.知識體系
1.為什么要用分布式事務(wù)
單體架構(gòu)時荒椭,以本地事務(wù)為例淆党,業(yè)務(wù)場景是下單場景佛致,用戶下單吼蚁、創(chuàng)建訂單凭需、扣減庫存這些操作都可以在一個數(shù)據(jù)庫事務(wù)中完成。
而隨著業(yè)務(wù)的增長肝匆,系統(tǒng)轉(zhuǎn)變?yōu)榉植际较到y(tǒng)粒蜈,原有的單體架構(gòu)也拆分為多個微服務(wù)。下單場景需要在多個服務(wù)間操作旗国,需要保證所有操作都能成功枯怖,保證整個下單流程的數(shù)據(jù)一致性,就需要用到分布式事務(wù)了
2.理論
- 分布式理論的CP -> 剛性事務(wù)
遵循ACID粗仓,對數(shù)據(jù)要求強(qiáng)一致性
- 分布式理論的AP+BASE -> 柔性事務(wù)
遵循BASE嫁怀,允許一定時間內(nèi)不同節(jié)點(diǎn)的數(shù)據(jù)不一致,但要求最終一致借浊。
這里重新復(fù)習(xí)一遍BASE理論是什么:
- 基本可用 Basically Available
- 軟狀態(tài) Soft State
- 最終一致性 Eventually Consistent
基本可用:是指系統(tǒng)出現(xiàn)未知故障時塘淑,還是能用的;
軟狀態(tài):允許系統(tǒng)存在中間態(tài)蚂斤,即所有副本數(shù)據(jù)允許存在延遲存捺;
最終一致性:存在軟狀態(tài),在一定時間后,所有副本數(shù)據(jù)保持一致捌治,從而達(dá)到數(shù)據(jù)最終一致性岗钩;
3.剛性事務(wù)(CP模式)
剛性事務(wù)指的是強(qiáng)一致性,基礎(chǔ)是XA協(xié)議肖油,XA協(xié)議是一個基于數(shù)據(jù)庫的分布式事務(wù)協(xié)議兼吓,其分為兩部分:事務(wù)管理器(Transaction Manager)*和*本地資源管理器(Resource Manager)**。事務(wù)管理器作為一個全局的調(diào)度者森枪,負(fù)責(zé)對各個本地資源管理器統(tǒng)一號令提交或者回滾视搏;
而2PC (兩階段提交)和3PC(三階段提交)都是由XA協(xié)議衍生出來的
3.1兩階段提交(2PC)
引入一個作為協(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ǎo)致數(shù)據(jù)不一致:第二階段協(xié)調(diào)者向參與者發(fā)送commit命令后,如果發(fā)生網(wǎng)絡(luò)抖動那伐,有一部分參與者未收到commit請求,則無法執(zhí)行事務(wù)提交石蔗,影響整個系統(tǒng)數(shù)據(jù)一致性罕邀;
- 超時導(dǎo)致的同步阻塞問題:2PC中所有參與者節(jié)點(diǎn)都是事務(wù)阻塞型,當(dāng)一個節(jié)點(diǎn)通信超時养距,其余參與者都會被阻塞诉探;
- 單點(diǎn)故障的風(fēng)險:整個過程嚴(yán)重依賴協(xié)調(diào)者,如果協(xié)調(diào)者故障棍厌,參與者處于鎖定資源的狀態(tài)肾胯,無法完成事務(wù)commit的操作。即使重新選擇一個協(xié)調(diào)者耘纱,也無法解決因前一個協(xié)調(diào)者宕機(jī)導(dǎo)致的阻塞問題敬肚;
2PC只適用于兩個數(shù)據(jù)庫(數(shù)據(jù)庫實(shí)現(xiàn)了XA協(xié)議)之間使用,限制較大束析,兩個系統(tǒng)間無法使用
3.2 三階段提交(3PC)
在2PC的基礎(chǔ)上艳馒,第一階段和第二階段中插入一個準(zhǔn)備階段,同時在協(xié)調(diào)者和參與者中都引入超時機(jī)制,當(dāng)參與者為收到協(xié)調(diào)者發(fā)送的commit請求后弄慰,也會對本地事務(wù)commit第美,不會一直阻塞等待
過程如下:
- 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請求衫樊,執(zhí)行事務(wù)的中斷;
- DoCommit:所有參與者已經(jīng)回復(fù)YES利花,協(xié)調(diào)者發(fā)DoCommit命令正式提交事務(wù)科侈,如果協(xié)調(diào)者沒有收到參與者的ACK響應(yīng),則發(fā)Abort請求給所有參與者炒事,中斷事務(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)用層面
三個操作步驟:
- Try階段:完成業(yè)務(wù)檢查,預(yù)留必須得業(yè)務(wù)資源甩鳄;
- Confirm階段:執(zhí)行業(yè)務(wù)邏輯逞度,只使用Try階段預(yù)留的業(yè)務(wù)資源。Confirm需滿足冪等性妙啃,保證一個分布式事務(wù)只成功一次第晰;
- Cancel階段:取消操作,釋放Try階段預(yù)留的業(yè)務(wù)資源,需要冪等性茁瘦;
4.2 Saga事務(wù)
Saga可以看做一個異步的品抽、利用隊(duì)列實(shí)現(xiàn)的補(bǔ)償事務(wù)。
由一系列本地事務(wù)構(gòu)成甜熔,每個本地事務(wù)更新了數(shù)據(jù)庫后圆恤,會發(fā)布一條消息來觸發(fā)Saga中的下一個本地事務(wù)的執(zhí)行,如果某個本地事務(wù)失敗了腔稀,Saga會執(zhí)行這個失敗事務(wù)之前 已提交的所有事務(wù)的補(bǔ)償操作
Saga的實(shí)現(xiàn)最流行的兩種方式是:
- 基于事件的方式盆昙。這種方式?jīng)]有協(xié)調(diào)中心,整個模式的工作方式就像舞蹈一樣焊虏,各個舞蹈演員按照預(yù)先編排的動作和走位各自表演淡喜,最終形成一只舞蹈。處于當(dāng)前Saga下的各個服務(wù)诵闭,會產(chǎn)生某類事件炼团,或者監(jiān)聽其它服務(wù)產(chǎn)生的事件并決定是否需要針對監(jiān)聽到的事件做出響應(yīng)。
- 基于命令的方式疏尿。這種方式的工作形式就像一只樂隊(duì)瘟芝,由一個指揮家(協(xié)調(diào)中心)來協(xié)調(diào)大家的工作。協(xié)調(diào)中心來告訴Saga的參與方應(yīng)該執(zhí)行哪一個本地事務(wù)
基于事件的方式
事務(wù)回滾:
- 基于事件的回滾褥琐,需要相關(guān)服務(wù)提供補(bǔ)償操作接口锌俱,某個節(jié)點(diǎn)發(fā)生無法執(zhí)行事件操作時,需要發(fā)送事件通知敌呈,其他已執(zhí)行了事務(wù)的節(jié)點(diǎn)監(jiān)聽事件并回應(yīng)
- 優(yōu)點(diǎn):簡單容易理解贸宏,適用于分布式事務(wù)只有2-4個步驟的場景。示例如:下單-扣款-庫存減貨-物流服務(wù)-訂單完成 這樣簡單的場景
- 缺點(diǎn):參與業(yè)務(wù)方多時磕洪,會出現(xiàn)很多問題
4.3本地消息表
本地消息表的核心是將分布式事務(wù)拆成本地事務(wù)進(jìn)行處理锚赤,最初是由eBay提出的
下面以一個訂單場景具體說明本地消息表的實(shí)現(xiàn)
例如,可以在訂單庫新增一個消息表褐鸥,將新增訂單和新增消息放到一個事務(wù)里完成,然后通過輪詢的方式去查詢消息表赐稽,將消息推送到 MQ叫榕,庫存服務(wù)去消費(fèi) MQ。
執(zhí)行流程為:
- 訂單服務(wù)姊舵,在一個事務(wù)里增加一個訂單和一條消息晰绎,并提交
- 訂單服務(wù)通過輪詢的方式,查出未同步的消息括丁,發(fā)到MQ荞下,從設(shè)置失敗重試機(jī)制;
- 庫存服務(wù),負(fù)責(zé)接收MQ消息尖昏,進(jìn)行消費(fèi)修改庫存仰税,由消費(fèi)方保證冪等性;
- 庫存服務(wù)修改成功后抽诉,調(diào)RPC接口修改訂單服務(wù)的消息表狀態(tài)陨簇;
- 修改失敗,等待重試
優(yōu)點(diǎn):方案輕量迹淌,消息可靠性不依賴消息中間件河绽;
缺點(diǎn):與業(yè)務(wù)強(qiáng)耦合,不可公用唉窃,消息數(shù)據(jù)與業(yè)務(wù)庫同庫耙饰,占資源;
4.4 MQ消息事務(wù)
MQ事務(wù)是對本地消息表的封裝纹份,將本地消息表存到MQ內(nèi)部了苟跪,而不是業(yè)務(wù)數(shù)據(jù)庫
將兩個事務(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ò)請求(half + commit/rolllback消息)
4.5 最大努力通知
也成為定期校對瞻惋,是對MQ事務(wù)的進(jìn)一步優(yōu)化。
事務(wù)發(fā)起方增加了消息校對接口援岩,也就是查詢接口歼狼,事務(wù)接收方可以自行調(diào)用接口主動獲取操作結(jié)果
邏輯如下:
事務(wù)主動方盡最大努力(重試,輪詢....)將事務(wù)發(fā)送給事務(wù)接收方享怀,但是仍然存在消息接收不到羽峰,此時需要事務(wù)被動方主動調(diào)用事務(wù)主動方的消息校對接口查詢業(yè)務(wù)消息并消費(fèi),這種通知的可靠性是由事務(wù)被動方保證的
適用場景:
業(yè)務(wù)通知類型的場景添瓷,如微信交易的結(jié)果梅屉,就是通過最大努力通知方式通知各個商戶,既有回調(diào)通知鳞贷,也有交易查詢接口
5. Seata框架
開源的分布式事務(wù)解決方案坯汤,提供了AT、TCC搀愧、SAGA惰聂、XA事務(wù)模式疆偿,不需要自己手動實(shí)現(xiàn)分布式事務(wù)嗜价,直接使用框架就行
有以下幾個角色:
- TC (Transaction Coordinator) - 事務(wù)協(xié)調(diào)者: 維護(hù)全局和分支事務(wù)的狀態(tài)扼睬,驅(qū)動全局事務(wù)提交或回滾挤忙。
- TM (Transaction Manager) - 事務(wù)管理器: 定義全局事務(wù)的范圍:開始全局事務(wù)塌忽、提交或回滾全局事務(wù)青伤。
- RM (Resource Manager) - 資源管理器: 管理分支事務(wù)處理的資源椎木,與TC交談以注冊分支事務(wù)和報(bào)告分支事務(wù)的狀態(tài)灭红,并驅(qū)動分支事務(wù)提交或回滾为肮。