分布式事務(wù)的解決方案

本文從以下幾個方面介紹分布式事務(wù)的解決方案:

  • 為什么會有分布式事務(wù)
  • 分布式事務(wù)經(jīng)典模型
  • 分布式事務(wù)解決方案

為什么會有分布式事務(wù)

假設(shè)有如下一個架構(gòu)再菊,這是一個簡單的電商架構(gòu)平臺,兩個應(yīng)用節(jié)點,一個數(shù)據(jù)庫,一個負載均衡器撼唾。這個架構(gòu)下,每天會產(chǎn)生將近 100W 的訂單量哥蔚。那么一個月的數(shù)據(jù)量就會超過 3000W倒谷。而隨著數(shù)據(jù)量的不斷擴大蛛蒙,對于訂單表的相關(guān)查詢操作的性能開銷就越來越大。并且響應(yīng)耗時也越來越長渤愁。這個時候我們需要考慮到數(shù)據(jù)庫的優(yōu)化問題牵祟。也就是對數(shù)據(jù)庫進行分表分庫,達到分攤數(shù)據(jù)庫壓力以及減少數(shù)據(jù)庫單表數(shù)據(jù)量的目的抖格。


分庫分表帶來的問題

分庫分表以后诺苹,一方面分擔了單庫帶來的性能壓力;另一方面雹拄,減少了單表的數(shù)據(jù)量收奔。完美的解決了我們遇到的性能問題。但是滓玖,隨著而來的又有另外的問題坪哄。

比如有這樣一個場景,訂單支付成功以后需要扣減庫存势篡。在數(shù)據(jù)庫分庫分表之前翩肌,所有數(shù)據(jù)都在同一個庫里面,可以通過事務(wù)操作就很容易達到數(shù)據(jù)一致性的目的禁悠。但是在數(shù)據(jù)庫做了拆分后摧阅,訂單狀態(tài)更新是屬于訂單的數(shù)據(jù)庫,而庫存扣減是屬于庫存的數(shù)據(jù)庫绷蹲。原本單庫的事務(wù)操作就變成了多庫的事務(wù)操作棒卷。



但是每個庫的事務(wù)只有自己知道,訂單庫并不知道庫存庫的事務(wù)執(zhí)行結(jié)果祝钢,庫存庫也不知道訂單庫的修改結(jié)果比规。所以就造成了分布式事務(wù)的問題。其實也叫分布式數(shù)據(jù)一致性拦英。

認識分布式事務(wù)

既然存在分布式事務(wù)的問題蜒什,那就一定有成熟的解決方案,接下來了解下業(yè)內(nèi)的常用解決方法及原理:

X/OpenDTP 事務(wù)模型

X/Open DTP(X/Open Distributed Transaction Processing Reference Model) 是X/Open 這個組織定義的一套分布式事務(wù)的標準疤估,也就是定義了規(guī)范和 API 接口灾常,由各個廠商進行具體的實現(xiàn)。

這個標準提出了使用二階段提交(2PC – Two-Phase-Commit)來保證分布式事務(wù)的完整性铃拇。后來 J2EE 也遵循了 X/OpenDTP 規(guī)范钞瀑,設(shè)計并實現(xiàn)了 java 里的分布式事務(wù)編程接口規(guī)范JTA。

X/OpenDTP 角色

在 X/OpenDTP 事務(wù)模型中慷荔,定義了三個角色:
AP: application, 應(yīng)用程序雕什,也就是業(yè)務(wù)層。哪些操作屬于一個事務(wù),就是 AP 定義的贷岸;
RM: Resource Manager壹士,資源管理器。一般是數(shù)據(jù)庫偿警,也可以是其他資源管理器躏救,比如消息隊列,文件系統(tǒng)螟蒸;
TM: Transaction Manager 落剪,事務(wù)管理器、事務(wù)協(xié)調(diào)者尿庐,負責接收來自用戶程序(AP)發(fā)起的 XA 事務(wù)指令,并調(diào)度和協(xié)調(diào)參與事務(wù)的所有 RM(數(shù)據(jù)庫)呢堰,確保事務(wù)正確完成抄瑟。

在分布式系統(tǒng)中,每一個機器節(jié)點雖然都能夠明確知道自己在進行事務(wù)操作過程中的結(jié)果是成功還是失敗枉疼,但卻無法直接獲取到其他分布式節(jié)點的操作結(jié)果。因此當一個事務(wù)操作需要跨越多個分布式節(jié)點的時候,為了保持事務(wù)處理的 ACID 特性尤误,就需要引入一個“協(xié)調(diào)者”(TM)來統(tǒng)一調(diào)度所有分布式節(jié)點的執(zhí)行邏輯哮兰,這些被調(diào)度的分布式節(jié)點被稱為 AP。TM 負責調(diào)度 AP 的行為航闺,并最終決定這些 AP 是否要把事務(wù)真正進行提交到(RM)褪测。



1、參與分布式事務(wù)的應(yīng)用程序(AP)先到 TM 上注冊全局事務(wù)
2潦刃、 然后各個 AP 直接在相應(yīng)的資源管理器(RM)上進行事務(wù)操作
3侮措、 操作完成以后,各個 AP 反饋事務(wù)的處理結(jié)果給到 TM
4乖杠、 TM 收到所有 AP 的反饋以后分扎,通過數(shù)據(jù)庫提供的 XA 接口進行數(shù)據(jù)提交或者回滾操作

2pc(two -phaseCommit)

在 X/OpenDTP 模型中,一個分布式事務(wù)所涉及的 SQL 邏輯都執(zhí)行完成胧洒,并到了RM最后要提交事務(wù)的關(guān)鍵時刻畏吓,為了避免分布式系統(tǒng)所固有的不可靠性導致提交事務(wù)意外失敗,TM 實施兩步走的方案卫漫,這個就稱為二階提交菲饼。

二階段提交,是計算機網(wǎng)絡(luò)尤其是在數(shù)據(jù)庫領(lǐng)域內(nèi)列赎,為了使基于分布式系統(tǒng)架構(gòu)下的所有節(jié)點在進行事務(wù)處理過程中能夠保持原子性和一致性而設(shè)計的一種算法巴粪。通常,二階段提交協(xié)議也被認為是一種一致性協(xié)議,用來保證分布式系統(tǒng)數(shù)據(jù)的一致性肛根。目前辫塌,絕大部分的關(guān)系型數(shù)據(jù)庫都是采用二階段提交協(xié)議來完成分布式事務(wù)處理的,利用該協(xié)議能夠非常方便地完成所有分布式事務(wù) AP 的協(xié)調(diào)派哲,統(tǒng)一決定事務(wù)的提交或回滾臼氨,從而能夠有效保證分布式數(shù)據(jù)一致性,因此 2pc 也被廣泛運用在許多分布式系統(tǒng)中芭届。

第一階段


1储矩、事務(wù)詢問
TM 向所有的 AP 發(fā)送事務(wù)內(nèi)容,詢問是否可以執(zhí)行事務(wù)提交操作褂乍,并開始等待各AP 的響應(yīng)持隧。
2、執(zhí)行事務(wù)
各個 AP 節(jié)點執(zhí)行事務(wù)操作逃片,并將 Undo 和 Redo 信息記錄到事務(wù)日志中屡拨,盡量把提交過程中所有消耗時間的操作和準備都提前完成確保后面 100%成功提交事務(wù)。
3褥实、各個 AP 向 TM 反饋事務(wù)詢問的響應(yīng)
如果各個 AP 成功執(zhí)行了事務(wù)操作呀狼,那么就反饋給 TM yes 的響應(yīng),表示事務(wù)可以執(zhí)行损离;如果 AP 沒有成功執(zhí)行事務(wù)哥艇,就反饋給 TM no 的響應(yīng),表示事務(wù)不可以執(zhí)行僻澎。

上面這個階段有點類似 TM 組織各個 AP 對一次事務(wù)操作的投票表態(tài)過程貌踏,因此2pc 協(xié)議的第一個階段稱為“投票階段”,即各 AP 投票表名是否需要繼續(xù)執(zhí)行接下去的事務(wù)提交操作窟勃。

第二階段


在這個階段哩俭,TM 會根據(jù)各 AP 的反饋情況來決定最終是否可以進行事務(wù)提交操作,正常情況下包含兩種可能:
提交事務(wù):
1拳恋、發(fā)送提交請求
TM 向所有 AP 節(jié)點發(fā)出 commit 請求
2凡资、事務(wù)提交
AP 接收到 Commit 請求后,會正式執(zhí)行事務(wù)提交操作谬运,并在完成提交之后釋放在整個事務(wù)執(zhí)行期間占用的事務(wù)資源
3隙赁、反饋事務(wù)提交結(jié)果
AP 在完成事務(wù)提交之后,向 TM 發(fā)送 Ack 消息
4梆暖、完成事務(wù)
TM 接收到所有 AP 反饋的 ack 消息后伞访,完成事務(wù)

事務(wù)回滾:
假設(shè)任何一個 AP 向 TM 反饋了 NO 的響應(yīng),或者在等待超時之后轰驳,TM 無法接收到所有 AP 的反饋響應(yīng)厚掷,那么就會中斷事務(wù)弟灼。
1、發(fā)送回滾請求
TM 向所有 AP 發(fā)出 rollback 請求
2冒黑、 事務(wù)回滾
AP 收到 rollback 請求后田绑,會利用在第一階段記錄的 Undo 信息來執(zhí)行事務(wù)回滾操作,并在完成回滾之后釋放在整個事務(wù)執(zhí)行期間占用的資源
3抡爹、 反饋事務(wù)回滾結(jié)果
各 AP 在完成事務(wù)回滾之后掩驱,向 TM 發(fā)送 Ack 消息
4、中斷事務(wù)
TM接收到所有 AP 反饋的 ack 消息后冬竟,完成事務(wù)中斷

二階段提交將一個事務(wù)的處理過程分為投票和執(zhí)行兩個階段欧穴。二階段提交的優(yōu)點在于,它充分考慮到了分布式系統(tǒng)的不可靠因素泵殴,并且采用非常簡單的方式(兩階段提交)就把由于系統(tǒng)不可靠從而導致事務(wù)提交失敗的概率降到最小涮帘。

假如一個事務(wù)的提交過程總共需要 30 秒的操作,其中 prepare 階段需要 28 秒(主要是確保事務(wù)日志落地磁盤等各種耗時的 I/O 操作)笑诅,真正的 commit 階段只需要花費兩秒调缨,那么 Commit 階段發(fā)生錯誤的概率與 Prepare 階段相比,只是它的2/28(<10%)苟鸯,也就是說,如果 Prepare 階段成功了棚点,則 Commit 階段由于時間非常短早处,失敗概率小,會大大增加分布式事務(wù)成功的概率瘫析。

2pc 的優(yōu)缺點
1砌梆、原理簡單,實現(xiàn)很方便
2贬循、 每一個階段都是同步阻塞咸包,會造成性能損耗
3、協(xié)調(diào)者存在單點問題杖虾,如果協(xié)調(diào)者在第二階段出現(xiàn)故障烂瘫,那么其他參與者會一直處于鎖定狀態(tài)
4、太過保守奇适,任意一個節(jié)點失敗都會導致數(shù)據(jù)回滾
5坟比、數(shù)據(jù)不一致問題: 在階段二中,當協(xié)調(diào)者向所有的參與者發(fā)送 commit 請求后嚷往,發(fā)生了網(wǎng)絡(luò)異常導致協(xié)調(diào)者在尚未發(fā)完 commit 請求之前崩潰葛账,可能會導致只有部分的參與者接收到 commit 請求,剩下沒收到 commit 請求的參與者將無法提交事務(wù)皮仁,也就可能導致數(shù)據(jù)不一致的問題

3PC

3PC 主要用來解決 2PC 的同步阻塞問題的一種優(yōu)化方案籍琳,3pc 分為 3 個階段分別為:cancommit菲宴、precommit、doCommit趋急。

和 2PC提交的區(qū)別在于:
(1) 在協(xié)調(diào)者和參與者中引入了超時機制(2pc 只有在協(xié)調(diào)者擁有超時機制,協(xié)調(diào)者在一定時間內(nèi)沒受到參與者的信息則默認為失敽嚷汀);
(2) 把 2 階段提交的第一個階段拆分成了兩個步驟宣谈。
cancommit 階段
協(xié)調(diào)者向參與者發(fā)送cancommit請求愈犹,參與者如果可以提交就返回 yes 的響應(yīng),否則返回 No 的響應(yīng)闻丑。這一階段主要是確定分布式事務(wù)的參與者是否具備了完成commit 的條件漩怎,并不會執(zhí)行事務(wù)操作。
precommit 階段
事務(wù)協(xié)調(diào)者根據(jù)參與者的反饋情況來決定是否繼續(xù)執(zhí)行事務(wù)的 precommit 操作嗦嗡,在這一個階段勋锤,會有兩種可能性,第一種是侥祭,在 cancommit 階段所有參與者都反饋的是 yes叁执,則會進行事務(wù)預(yù)執(zhí)行。另一種是矮冬,任意一個事務(wù)參與者在第一階段返回了 no谈宛,則執(zhí)行事務(wù)中斷請求。
docommit 階段
同2PC docommit一致

JTA 事務(wù)模型

在 java 中胎署,分布式事務(wù)主要的規(guī)范是 JTA吆录。JTA 是 java 的事務(wù)管理器規(guī)范,JTA 全稱為 Java Transaction API琼牧,JTA 定義了一組統(tǒng)一的事務(wù)編程的接口恢筝,基于X/OpenDTP 規(guī)范設(shè)計的分布式事務(wù)編程接口規(guī)范【薹唬基于 JTA 規(guī)范的第三方分布式事務(wù)框架有JOTM 和 Atomikos撬槽。

JOTM

JOTM (java open transaction manager)是 ObjectWeb 的一個開源 JTA 實現(xiàn),提
供 JTA 分布式事務(wù)的功能趾撵。但是 JOTM 存在一個問題侄柔,在使用中不能自動 rollback,無論什么情況都 commit占调。

Atomikos

與 JOTM 相比勋拟,Atomikos 更加穩(wěn)定,原本 Atomikos 是商業(yè)項目妈候,后來開源敢靡。論壇比較活躍,有問題可以隨時得到解決苦银。

其他分布式事務(wù)解決方案

目前互聯(lián)網(wǎng)領(lǐng)域里有幾種流行的分布式解決方案啸胧,但都沒有像之前所說的 XA 事務(wù)一樣形成 X/OpenDTP 那樣的工業(yè)規(guī)范赶站,而是僅僅在具體的行業(yè)里獲得較多的認可。

我們知道纺念,對于 CAP 來說贝椿,對于共享數(shù)據(jù)的系統(tǒng),由于網(wǎng)絡(luò)分區(qū)問題的存在陷谱,我們只能滿足 AP 或者 CP烙博;對于 BASE 理論,滿足基本可用烟逊。所以其實我們在落地數(shù)據(jù)一致性解決方案是渣窜,基本上都會選擇一個平衡點,也就是酸堿平衡理論宪躯,ACID 是酸乔宿、 BASE 是堿;ACID 是強一致性访雪、BASE 是弱一致性详瑞。強一致性代表數(shù)據(jù)庫本身不會出現(xiàn)不一致,每個事務(wù)是原子的臣缀,或者成功或者失敗坝橡,事物間是隔離的,互相完全不影響精置,而且最終狀態(tài)是持久落盤的计寇,因此,數(shù)據(jù)庫會從一個明確的狀態(tài)到另外一個明確的狀態(tài).; 而 BASE 體現(xiàn)的是最終一致性氯窍,允許出現(xiàn)中間狀態(tài)饲常。

所以對于服務(wù)來說蹲堂,有很多的方案去選擇:
1狼讨、提供查詢服務(wù)確認數(shù)據(jù)狀態(tài);2柒竞、冪等操作對于重發(fā)保證數(shù)據(jù)的安全性政供;3、TCC事務(wù)操作朽基;4布隔、補償操作;5稼虎、定期校對等

TCC

TCC 事務(wù)解決方案本質(zhì)上是一種補償?shù)乃悸沸铺矗咽聞?wù)運行過程分成 Try、Confirm/Cancel 兩個階段霎俩,每個階段由業(yè)務(wù)代碼控制哀军,這樣事務(wù)的鎖力度可以完全自由控制沉眶。需要注意的是,TCC 事務(wù)和 2pc 的思想類似杉适,但并不是 2pc 的實現(xiàn)谎倔,TCC 不再是兩階段提交,而只是它對事務(wù)的提交/回滾是通過執(zhí)行一段 confirm/cancel 業(yè)務(wù)邏輯來實現(xiàn)猿推,并且也并沒有全局事務(wù)來把控整個事務(wù)邏輯片习。

業(yè)務(wù)接口整合,避免分布式事務(wù)

這個方案就是把一個業(yè)務(wù)流程中需要在一個事務(wù)里執(zhí)行的多個相關(guān)業(yè)務(wù)接口包裝整合到一個事務(wù)中蹬叭,比如我們可以講 A/B/C 整合為一個服務(wù) D 來實現(xiàn)單一事務(wù)的業(yè)務(wù)流程服務(wù)藕咏。

最終一致性方案

eBay 在 2008 年公布了一個關(guān)于 BASE 準則提到一個分布式事務(wù)解決方案。eBay的方案其實是一個最終一致性方案具垫,它主要采用消息隊列來輔助實現(xiàn)事務(wù)控制流程侈离,方案的核心是將需要分布式處理的任務(wù)通過消息隊列的方式來異步執(zhí)行,如果事務(wù)失敗筝蚕,則可以發(fā)起人工重試的糾正流程卦碾。人工重試被更多的應(yīng)用于支付場景,通過對賬系統(tǒng)對事后問題進行處理起宽。

關(guān)于狀態(tài)機

在使用最終一致性的方案時洲胖,一定要提到的一個概念是狀態(tài)機。

什么是狀態(tài)機坯沪?是一種特殊的組織代碼的方式绿映,用這種方式能夠確保你的對象隨時都知道自己所處的狀態(tài)以及所能做的操作。它也是一種用來進行對象行為建模的工具腐晾,用于描述對象在它的生命周期內(nèi)所經(jīng)歷的狀態(tài)序列叉弦,以及如何響應(yīng)來自外界的各種事件。

以支付為例藻糖,一筆訂單可能會有等待支付淹冰、支付中、已支付等狀態(tài)巨柒,那么我們就可以先去把可能出現(xiàn)的狀態(tài)以及狀態(tài)的流程畫出來樱拴。



狀態(tài)機的兩個作用:
1、實現(xiàn)冪等
2洋满、 通過狀態(tài)驅(qū)動數(shù)據(jù)的變化

什么是冪等

簡單來說就是重復(fù)調(diào)用多次產(chǎn)生的業(yè)務(wù)結(jié)果與調(diào)用一次產(chǎn)生的業(yè)務(wù)結(jié)果相同晶乔。 在分布式架構(gòu)中,我們調(diào)用一個遠程服務(wù)去完成一個操作牺勾,除了成功和失敗以外正罢,還有未知狀態(tài),那么針對這個未知狀態(tài)驻民,我們會采取一些重試的行為翻具; 或者在消息中間件的使用場景中袱饭,消費者可能會重復(fù)收到消息。對于這兩種情況呛占,消費端或者服務(wù)端需要采取一定的手段虑乖,也就是考慮到重發(fā)的情況下保證數(shù)據(jù)的安全性。一般我們常用的手段:
1晾虑、狀態(tài)機實現(xiàn)冪等
2疹味、數(shù)據(jù)庫唯一約束實現(xiàn)冪等
3、通過 id 的方式去識別每次請求判斷是否重復(fù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末帜篇,一起剝皮案震驚了整個濱河市糙捺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笙隙,老刑警劉巖洪灯,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異竟痰,居然都是意外死亡签钩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門坏快,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铅檩,“玉大人,你說我怎么就攤上這事莽鸿∶林迹” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵祥得,是天一觀的道長兔沃。 經(jīng)常有香客問我,道長级及,這世上最難降的妖魔是什么乒疏? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮创千,結(jié)果婚禮上缰雇,老公的妹妹穿的比我還像新娘入偷。我一直安慰自己追驴,他們只是感情好,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布疏之。 她就那樣靜靜地躺著殿雪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锋爪。 梳的紋絲不亂的頭發(fā)上丙曙,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天爸业,我揣著相機與錄音,去河邊找鬼亏镰。 笑死扯旷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的索抓。 我是一名探鬼主播钧忽,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逼肯!你這毒婦竟也來了耸黑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤篮幢,失蹤者是張志新(化名)和其女友劉穎大刊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體三椿,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡缺菌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了搜锰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片男翰。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖纽乱,靈堂內(nèi)的尸體忽然破棺而出蛾绎,到底是詐尸還是另有隱情,我是刑警寧澤鸦列,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布租冠,位于F島的核電站,受9級特大地震影響薯嗤,放射性物質(zhì)發(fā)生泄漏顽爹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一骆姐、第九天 我趴在偏房一處隱蔽的房頂上張望镜粤。 院中可真熱鬧,春花似錦玻褪、人聲如沸肉渴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽同规。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間券勺,已是汗流浹背绪钥。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留关炼,地道東北人程腹。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像儒拂,于是被迫代替她去往敵國和親跪楞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容