分布式事務(wù)中間件Seata的設(shè)計原理

微信公眾號「后端進階」,專注后端技術(shù)分享:Java懂从、Golang授段、WEB框架察迟、分布式中間件伏尼、服務(wù)治理等等。

在微服務(wù)架構(gòu)體系下贴彼,我們可以按照業(yè)務(wù)模塊分層設(shè)計缘薛,單獨部署窍育,減輕了服務(wù)部署壓力,也解耦了業(yè)務(wù)的耦合宴胧,避免了應(yīng)用逐漸變成一個龐然怪物漱抓,從而可以輕松擴展,在某些服務(wù)出現(xiàn)故障時也不會影響其它服務(wù)的正常運行恕齐∑蚵Γ總之,微服務(wù)在業(yè)務(wù)的高速發(fā)展中帶給我們越來越多的優(yōu)勢,但是微服務(wù)并不是十全十美仪或,因此不能盲目過度濫用确镊,它有很多不足,而且會給系統(tǒng)帶來一定的復(fù)雜度范删,其中伴隨而來的分布式事務(wù)問題蕾域,是微服務(wù)架構(gòu)體系下必然需要處理的一個痛點,也是業(yè)界一直關(guān)注的一個領(lǐng)域到旦,因此也出現(xiàn)了諸如 CAP 和 BASE 等理論旨巷。

在今年年初,阿里開源了一個分布式事務(wù)中間件添忘,起初起名為 Fescar采呐,后改名為 Seata,在它開源之初昔汉,我就知道它肯定要火懈万,因為這是一個解決痛點的開源項目,Seata 一開始就是沖著對業(yè)務(wù)無侵入與高性能方向走靶病,這正是我們對解決分布式事務(wù)問題迫切的需求。因為待過的幾家公司口予,用的都是微服務(wù)架構(gòu)娄周,但是在解決分布式事務(wù)的問題上都不太優(yōu)雅,所以我也在一直關(guān)注 Seata 的發(fā)展沪停,今天就簡要說說它的一些設(shè)計上的原理煤辨,后續(xù)我將會對它的各個模塊進行深入源碼分析,感興趣的可以持續(xù)關(guān)注我的公眾號或者博客木张,不要跟丟众辨。

分布式事務(wù)解決的方案有哪些?

目前分布式事務(wù)解決的方案主要有對業(yè)務(wù)無入侵和有入侵的方案舷礼,無入侵方案主要有基于數(shù)據(jù)庫 XA 協(xié)議的兩段式提交(2PC)方案鹃彻,它的優(yōu)點是對業(yè)務(wù)代碼無入侵,但是它的缺點也是很明顯:必須要求數(shù)據(jù)庫對 XA 協(xié)議的支持妻献,且由于 XA 協(xié)議自身的特點蛛株,它會造成事務(wù)資源長時間得不到釋放,鎖定周期長育拨,而且在應(yīng)用層上面無法干預(yù)谨履,因此它性能很差,它的存在相當(dāng)于七傷拳那樣“傷人七分熬丧,損己三分”笋粟,因此在互聯(lián)網(wǎng)項目中并不是很流行這種解決方案。

為了這個彌補這種方案帶來性能低的問題,大佬們又想出了很多種方案來解決害捕,但這無一例外都需要通過在應(yīng)用層做手腳唆香,即入侵業(yè)務(wù)的方式,比如很出名的 TCC 方案吨艇,基于 TCC 也有很多成熟的框架躬它,如 ByteTCC、tcc-transaction 等东涡。以及基于可靠消息的最終一致性來實現(xiàn)冯吓,如 RocketMQ 的事務(wù)消息。

入侵代碼的方案是基于現(xiàn)有情形“迫不得已”才推出的解決方案疮跑,實際上它們實現(xiàn)起來非常不優(yōu)雅组贺,一個事務(wù)的調(diào)用通常伴隨而來的是對該事務(wù)接口增加一系列的反向操作,比如 TCC 三段式提交祖娘,提交邏輯必然伴隨著回滾的邏輯失尖,這樣的代碼會使得項目非常臃腫,維護成本高渐苏。

Seata 各模塊之間的關(guān)系

針對上面所說的分布式事務(wù)解決方案的痛點掀潮,那很顯然,我們理想的分布式事務(wù)解決方案肯定是性能要好而且要對業(yè)務(wù)無入侵琼富,業(yè)務(wù)層上無需關(guān)心分布式事務(wù)機制的約束仪吧,Seata 正是往這個方向發(fā)展的,因此它非常值得期待鞠眉,它將給我們的微服務(wù)架構(gòu)帶來質(zhì)的提升薯鼠。

那 Seata 是怎么做到的呢?下面說說它的各個模塊之間的關(guān)系械蹋。

Seata 的設(shè)計思路是將一個分布式事務(wù)可以理解成一個全局事務(wù)出皇,下面掛了若干個分支事務(wù),而一個分支事務(wù)是一個滿足 ACID 的本地事務(wù)哗戈,因此我們可以操作分布式事務(wù)像操作本地事務(wù)一樣郊艘。

Seata 內(nèi)部定義了 3個模塊來處理全局事務(wù)和分支事務(wù)的關(guān)系和處理過程,這三個組件分別是:

  • Transaction Coordinator (TC): 事務(wù)協(xié)調(diào)器谱醇,維護全局事務(wù)的運行狀態(tài)暇仲,負(fù)責(zé)協(xié)調(diào)并驅(qū)動全局事務(wù)的提交或回滾。
  • Transaction Manager (TM): 控制全局事務(wù)的邊界副渴,負(fù)責(zé)開啟一個全局事務(wù)奈附,并最終發(fā)起全局提交或全局回滾的決議。
  • Resource Manager (RM): 控制分支事務(wù)煮剧,負(fù)責(zé)分支注冊斥滤、狀態(tài)匯報将鸵,并接收事務(wù)協(xié)調(diào)器的指令,驅(qū)動分支(本地)事務(wù)的提交和回滾佑颇。
image

簡要說說整個全局事務(wù)的執(zhí)行步驟:

  1. TM 向 TC 申請開啟一個全局事務(wù)顶掉,TC 創(chuàng)建全局事務(wù)后返回全局唯一的 XID,XID 會在全局事務(wù)的上下文中傳播挑胸;
  2. RM 向 TC 注冊分支事務(wù)痒筒,該分支事務(wù)歸屬于擁有相同 XID 的全局事務(wù);
  3. TM 向 TC 發(fā)起全局提交或回滾茬贵;
  4. TC 調(diào)度 XID 下的分支事務(wù)完成提交或者回滾簿透。

與 XA 方案有什么不同?

Seata 的事務(wù)提交方式跟 XA 協(xié)議的兩段式提交在總體上來說基本是一致的解藻,那它們之間有什么不同呢老充?

我們都知道 XA 協(xié)議它依賴的是數(shù)據(jù)庫層面來保障事務(wù)的一致性,也即是說 XA 的各個分支事務(wù)是在數(shù)據(jù)庫層面上驅(qū)動的螟左,由于 XA 的各個分支事務(wù)需要有 XA 的驅(qū)動程序啡浊,一方面會導(dǎo)致數(shù)據(jù)庫與 XA 驅(qū)動耦合,另一方面它會導(dǎo)致各個分支的事務(wù)資源鎖定周期長胶背,這也是它沒有在互聯(lián)網(wǎng)公司流行的重要因素巷嚣。

基于 XA 協(xié)議以上的問題,Seata 另辟蹊徑奄妨,既然在依賴數(shù)據(jù)庫層會導(dǎo)致這么多問題涂籽,那我就從應(yīng)用層做手腳,這還得從 Seata 的 RM 模塊說起砸抛,前面也說過 RM 的主要作用了,其實 RM 在內(nèi)部做了對數(shù)據(jù)庫操作的代理層树枫,如下:

image

Seata 在數(shù)據(jù)源做了一層代理層直焙,所以我們使用 Seata 時,我們使用的數(shù)據(jù)源實際上用的是 Seata 自帶的數(shù)據(jù)源代理 DataSourceProxy砂轻,Seata 在這層代理中加入了很多邏輯奔誓,主要是解析 SQL,把業(yè)務(wù)數(shù)據(jù)在更新前后的數(shù)據(jù)鏡像組織成回滾日志搔涝,并將 undo log 日志插入 undo_log 表中厨喂,保證每條更新數(shù)據(jù)的業(yè)務(wù) sql 都有對應(yīng)的回滾日志存在。

這樣做的好處就是庄呈,本地事務(wù)執(zhí)行完可以立即釋放本地事務(wù)鎖定的資源蜕煌,然后向 TC 上報分支狀態(tài)。當(dāng) TM 決議全局提交時诬留,就不需要同步協(xié)調(diào)處理了斜纪,TC 會異步調(diào)度各個 RM 分支事務(wù)刪除對應(yīng)的 undo log 日志即可贫母,這個步驟非常快速地可以完成盒刚;當(dāng) TM 決議全局回滾時腺劣,RM 收到 TC 發(fā)送的回滾請求,RM 通過 XID 找到對應(yīng)的 undo log 回滾日志因块,然后執(zhí)行回滾日志完成回滾操作橘原。

image

如上圖所示,XA 方案的 RM 是放在數(shù)據(jù)庫層的涡上,它依賴了數(shù)據(jù)庫的 XA 驅(qū)動程序趾断。

image

如上圖所示,Seata 的 RM 實際上是已中間件的形式放在應(yīng)用層吓懈,不用依賴數(shù)據(jù)庫對協(xié)議的支持歼冰,完全剝離了分布式事務(wù)方案對數(shù)據(jù)庫在協(xié)議支持上的要求。

分支事務(wù)如何提交和回滾耻警?

下面詳細(xì)說說分支事務(wù)是如何提交和回滾的:

  • 第一階段:

分支事務(wù)利用 RM 模塊中對 JDBC 數(shù)據(jù)源代理隔嫡,加入了若干流程,對業(yè)務(wù) SQL 進行解釋甘穿,把業(yè)務(wù)數(shù)據(jù)在更新前后的數(shù)據(jù)鏡像組織成回滾日志腮恩,并生成 undo log 日志,對全局事務(wù)鎖的檢查以及分支事務(wù)的注冊等温兼,利用本地事務(wù) ACID 特性秸滴,將業(yè)務(wù) SQL 和 undo log 寫入同一個事物中一同提交到數(shù)據(jù)庫中,保證業(yè)務(wù) SQL 必定存在相應(yīng)的回滾日志募判,最后對分支事務(wù)狀態(tài)向 TC 進行上報荡含。

image
  • 第二階段:

TM決議全局提交:

當(dāng) TM 決議提交時,就不需要同步協(xié)調(diào)處理了届垫,TC 會異步調(diào)度各個 RM 分支事務(wù)刪除對應(yīng)的 undo log 日志即可释液,這個步驟非常快速地可以完成装处。這個機制對于性能提升非常關(guān)鍵误债,我們知道正常的業(yè)務(wù)運行過程中,事務(wù)執(zhí)行的成功率是非常高的妄迁,因此可以直接在本地事務(wù)中提交寝蹈,這步對于提升性能非常顯著。

image

TM決議全局回滾:

當(dāng) TM 決議回滾時登淘,RM 收到 TC 發(fā)送的回滾請求箫老,RM 通過 XID 找到對應(yīng)的 undo log 回滾日志,然后利用本地事務(wù) ACID 特性形帮,執(zhí)行回滾日志完成回滾操作并刪除 undo log 日志槽惫,最后向 TC 進行回滾結(jié)果上報周叮。

image

業(yè)務(wù)對以上所有的流程都無感知,業(yè)務(wù)完全不關(guān)心全局事務(wù)的具體提交和回滾界斜,而且最重要的一點是 Seata 將兩段式提交的同步協(xié)調(diào)分解到各個分支事務(wù)中了仿耽,分支事務(wù)與普通的本地事務(wù)無任何差異,這意味著我們使用 Seata 后各薇,分布式事務(wù)就像使用本地事務(wù)一樣项贺,完全將數(shù)據(jù)庫層的事務(wù)協(xié)調(diào)機制交給了中間件層 Seata 去做了,這樣雖然事務(wù)協(xié)調(diào)搬到應(yīng)用層了峭判,但是依然可以做到對業(yè)務(wù)的零侵入开缎,從而剝離了分布式事務(wù)方案對數(shù)據(jù)庫在協(xié)議支持上的要求,且 Seata 在分支事務(wù)完成之后直接釋放資源林螃,極大減少了分支事務(wù)對資源的鎖定時間奕删,完美避免了 XA 協(xié)議需要同步協(xié)調(diào)導(dǎo)致資源鎖定時間過長的問題。

其它方案的補充

上面說的其實是 Seata 的默認(rèn)模式疗认,也叫 AT 模式完残,它是類似于 XA 方案的兩段式提交方案,并且是對業(yè)務(wù)無侵入横漏,但是這種機制依然是需要依賴數(shù)據(jù)庫本地事務(wù)的 ACID 特性谨设,有沒有發(fā)現(xiàn),我在上面的圖中都強調(diào)了必須是支持 ACID 特性的關(guān)系型數(shù)據(jù)庫缎浇,那么問題就來了扎拣,非關(guān)系型或者不支持 ACID 的數(shù)據(jù)庫就無法使用 Seata 了,別慌素跺,Seata 現(xiàn)階段為我們準(zhǔn)備了另外一種模式二蓝,叫 MT 模式,它是一種對業(yè)務(wù)有入侵的方案指厌,提交回滾等操作需要我們自行定義侣夷,業(yè)務(wù)邏輯需要被分解為 Prepare/Commit/Rollback 3 部分,形成一個 MT 分支仑乌,加入全局事務(wù),它存在的意義是為 Seata 觸達更多的場景琴锭。

image

只不過晰甚,它不是 Seata “主打”的模式,它的存在僅僅作為補充的方案决帖,從以上官方的發(fā)展遠(yuǎn)景就可以看出來厕九,Seata 的目標(biāo)是始終是對業(yè)務(wù)無入侵的方案。

注:本文圖片設(shè)計參考Seata官方圖

公眾號「后端進階」地回,專注后端技術(shù)分享扁远!
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末俊鱼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子畅买,更是在濱河造成了極大的恐慌并闲,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谷羞,死亡現(xiàn)場離奇詭異帝火,居然都是意外死亡,警方通過查閱死者的電腦和手機湃缎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門犀填,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人嗓违,你說我怎么就攤上這事九巡。” “怎么了蹂季?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵冕广,是天一觀的道長。 經(jīng)常有香客問我乏盐,道長佳窑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任父能,我火速辦了婚禮神凑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘何吝。我一直安慰自己溉委,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布爱榕。 她就那樣靜靜地躺著瓣喊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪黔酥。 梳的紋絲不亂的頭發(fā)上藻三,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音跪者,去河邊找鬼棵帽。 笑死,一個胖子當(dāng)著我的面吹牛渣玲,可吹牛的內(nèi)容都是我干的逗概。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼忘衍,長吁一口氣:“原來是場噩夢啊……” “哼逾苫!你這毒婦竟也來了卿城?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤铅搓,失蹤者是張志新(化名)和其女友劉穎瑟押,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狸吞,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡勉耀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蹋偏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片便斥。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖威始,靈堂內(nèi)的尸體忽然破棺而出枢纠,到底是詐尸還是另有隱情,我是刑警寧澤黎棠,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布晋渺,位于F島的核電站,受9級特大地震影響脓斩,放射性物質(zhì)發(fā)生泄漏木西。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一随静、第九天 我趴在偏房一處隱蔽的房頂上張望八千。 院中可真熱鬧,春花似錦燎猛、人聲如沸恋捆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沸停。三九已至,卻和暖如春昭卓,著一層夾襖步出監(jiān)牢的瞬間愤钾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工候醒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留绰垂,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓火焰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胧沫。 傳聞我的和親對象是個殘疾皇子昌简,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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