分布式事務(wù)最經(jīng)典的七種解決方案
來源:segmentfault.com/a/1190000040321750
◆ 基礎(chǔ)理論
◆ 事務(wù)
把多條語句作為一個(gè)整體進(jìn)行操作的功能,被稱為數(shù)據(jù)庫事務(wù)。數(shù)據(jù)庫事務(wù)可以確保該事務(wù)范圍內(nèi)的所有操作都可以全部成功或者全部失敗。
事務(wù)具有 4 個(gè)屬性:原子性、一致性、隔離性、持久性。這四個(gè)屬性通常稱為 ACID 特性。
Consistency(一致性):在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性沒有被破壞。完整性包括外鍵約束、應(yīng)用定義的等約束不會被破壞。
Durability(持久性):事務(wù)處理結(jié)束后,對數(shù)據(jù)的修改就是永久的,即便系統(tǒng)故障也不會丟失。
◆ 分布式事務(wù)
柔性狀態(tài)(Soft state)
最終一致性(Eventual consistency)
同樣的,分布式事務(wù)也部分遵循 ACID 規(guī)范:
一致性:事務(wù)完成后的一致性嚴(yán)格遵循;事務(wù)中的一致性可適當(dāng)放寬
隔離性:并行事務(wù)間不可影響;事務(wù)中間結(jié)果可見性允許安全放寬
持久性:嚴(yán)格遵循
◆ 分布式事務(wù)的解決方案
◆ 兩階段提交/XA
把上面的轉(zhuǎn)賬作為例子,一個(gè)成功完成的XA事務(wù)時(shí)序圖如下:

如果有任何一個(gè)參與者prepare失敗,那么TM會通知所有完成prepare的參與者進(jìn)行回滾。
如果讀者想要進(jìn)一步研究XA,go語言可參考DTM,java語言可參考seata
◆ SAGA
Saga是這一篇數(shù)據(jù)庫論文saga提到的一個(gè)方案。其核心思想是將長事務(wù)拆分為多個(gè)本地短事務(wù),由Saga事務(wù)協(xié)調(diào)器協(xié)調(diào),如果正常結(jié)束那就正常完成,如果某個(gè)步驟失敗,則根據(jù)相反順序一次調(diào)用補(bǔ)償操作。
把上面的轉(zhuǎn)賬作為例子,一個(gè)成功完成的SAGA事務(wù)時(shí)序圖如下:

SAGA事務(wù)的特點(diǎn):
論文里面的SAGA內(nèi)容較多,包括兩種恢復(fù)策略,包括分支事務(wù)并發(fā)執(zhí)行,我們這里的討論,僅包括最簡單的SAGA
SAGA適用的場景較多,長事務(wù)適用,對中間結(jié)果不敏感的業(yè)務(wù)場景適用
如果讀者想要進(jìn)一步研究SAGA,go語言可參考DTM,java語言可參考seata
◆ TCC
關(guān)于 TCC(Try-Confirm-Cancel)的概念,最早是由 Pat Helland 于 2007 年發(fā)表的一篇名為《Life beyond Distributed Transactions:an Apostate’s Opinion》的論文提出。
Try 階段:嘗試執(zhí)行,完成所有業(yè)務(wù)檢查(一致性), 預(yù)留必須業(yè)務(wù)資源(準(zhǔn)隔離性) Confirm 階段:確認(rèn)執(zhí)行真正執(zhí)行業(yè)務(wù),不作任何業(yè)務(wù)檢查,只使用 Try 階段預(yù)留的業(yè)務(wù)資源,Confirm 操作要求具備冪等設(shè)計(jì),Confirm 失敗后需要進(jìn)行重試。 Cancel 階段:取消執(zhí)行,釋放 Try 階段預(yù)留的業(yè)務(wù)資源。Cancel 階段的異常和 Confirm 階段異常處理方案基本上一致,要求滿足冪等設(shè)計(jì)。
把上面的轉(zhuǎn)賬作為例子,通常會在Try里面凍結(jié)金額,但不扣款,Confirm里面扣款,Cancel里面解凍金額,一個(gè)成功完成的TCC事務(wù)時(shí)序圖如下:

TCC的Confirm/Cancel階段在業(yè)務(wù)邏輯上是不允許返回失敗的,如果因?yàn)榫W(wǎng)絡(luò)或者其他臨時(shí)故障,導(dǎo)致不能返回成功,TM會不斷的重試,直Confirm/Cancel返回成功。
TCC特點(diǎn)如下:
如果讀者想要進(jìn)一步研究TCC,go語言可參考DTM,java語言可參考seata
◆ 本地消息表
本地消息表這個(gè)方案最初是 ebay 架構(gòu)師 Dan Pritchett 在 2008 年發(fā)表給 ACM 的文章。設(shè)計(jì)核心是將需要分布式處理的任務(wù)通過消息的方式來異步確保執(zhí)行。
大致流程如下:

搜索公眾號互聯(lián)網(wǎng)架構(gòu)師后臺回復(fù)“2T”,獲取一份驚喜禮包。
容錯(cuò)機(jī)制:
本地消息表的特點(diǎn):
適用于可異步執(zhí)行的業(yè)務(wù),且后續(xù)操作無需回滾的業(yè)務(wù)
◆ 事務(wù)消息
根據(jù)發(fā)送結(jié)果執(zhí)行本地事務(wù)(如果寫入失敗,此時(shí)half消息對業(yè)務(wù)不可見,本地邏輯不執(zhí)行)
根據(jù)本地事務(wù)狀態(tài)執(zhí)行Commit或者Rollback(Commit操作發(fā)布消息,消息對消費(fèi)者可見)
正常發(fā)送的流程圖如下:

事務(wù)消息特點(diǎn)如下:
適用于可異步執(zhí)行的業(yè)務(wù),且后續(xù)操作無需回滾的業(yè)務(wù)
如果讀者想要進(jìn)一步研究事務(wù)消息,可參考rocketmq,為了方便大家學(xué)習(xí)事務(wù)消息,DTM也提供了簡單實(shí)現(xiàn)
◆ 最大努力通知
消息校對機(jī)制。如果盡最大努力也沒有通知到接收方,或者接收方消費(fèi)消息后要再次消費(fèi),此時(shí)可由接收方主動向通知方查詢消息信息來滿足需求。
前面介紹的的本地消息表和事務(wù)消息都屬于可靠消息,與這里介紹的最大努力通知有什么不同?
解決方案上,最大努力通知需要:
最大努力通知適用于業(yè)務(wù)通知類型,例如微信交易的結(jié)果,就是通過最大努力通知方式通知各個(gè)商戶,既有回調(diào)通知,也有交易查詢接口
◆ AT事務(wù)模式
這是阿里開源項(xiàng)目seata中的一種事務(wù)模式,在螞蟻金服也被稱為FMT。優(yōu)點(diǎn)是該事務(wù)模式使用方式,類似XA模式,業(yè)務(wù)無需編寫各類補(bǔ)償操作,回滾由框架自動完成,缺點(diǎn)也類似AT,存在較長時(shí)間的鎖,不滿足高并發(fā)的場景。有興趣的同學(xué)可以參考seata-AT
◆ 分布式事務(wù)中的網(wǎng)絡(luò)異常
在分布式事務(wù)的各個(gè)環(huán)節(jié)都有可能出現(xiàn)網(wǎng)絡(luò)以及業(yè)務(wù)故障等問題,這些問題需要分布式事務(wù)的業(yè)務(wù)方做到防空回滾,冪等,防懸掛三個(gè)特性,下面以TCC事務(wù)說明這些異常情況:
空回滾:
冪等:
由于任何一個(gè)請求都可能出現(xiàn)網(wǎng)絡(luò)異常,出現(xiàn)重復(fù)請求,所以所有的分布式事務(wù)分支,都需要保證冪等性
懸掛:
懸掛就是對于一個(gè)分布式事務(wù),其二階段 Cancel 接口比 Try 接口先執(zhí)行。
下面看一個(gè)網(wǎng)絡(luò)異常的時(shí)序圖,更好的理解上述幾種問題

在項(xiàng)目DTM中,出現(xiàn)了一種子事務(wù)屏障技術(shù),使用該技術(shù),能夠達(dá)到這個(gè)效果,看示意圖:

func ThroughBarrierCall(db *sql.DB, transInfo *TransInfo, busiCall BusiFunc)
如果是Try分支,則那么insert ignore插入gid-branchid-try,如果成功插入,則調(diào)用屏障內(nèi)邏輯
如果是Confirm分支,那么insert ignore插入gid-branchid-confirm,如果成功插入,則調(diào)用屏障內(nèi)邏輯
在此機(jī)制下,解決了網(wǎng)絡(luò)異常相關(guān)的問題
空補(bǔ)償控制--如果Try沒有執(zhí)行,直接執(zhí)行了Cancel,那么Cancel插入gid-branchid-try會成功,不走屏障內(nèi)的邏輯,保證了空補(bǔ)償控制
防懸掛控制--Try在Cancel之后執(zhí)行,那么插入的gid-branchid-try不成功,就不執(zhí)行,保證了防懸掛控制
對于SAGA事務(wù),也是類似的機(jī)制。
◆ 總結(jié)
感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。
正文結(jié)束
1.不認(rèn)命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事
3.從零開始搭建創(chuàng)業(yè)公司后臺技術(shù)棧
5.37歲程序員被裁,120天沒找到工作,無奈去小公司,結(jié)果懵了...
6.IntelliJ IDEA 2019.3 首個(gè)最新訪問版本發(fā)布,新特性搶先看

