蚂蚁金服大规模分布式事务实践和开源历程
本文整理自螞蟻金服技術專家、分布式事務 Seata 發起者之一張森(花名:紹輝)在 GIAC 全球互聯網架構大會的分享。10幾年的經驗,今天全部公開和開源。
一、自研分布式事務解決數據一致性問題
1.1 分布式事務問題產生原因
1.1.1 數據庫的水平拆分
螞蟻金服的業務數據庫起初是單庫單表,但隨著業務數據規模的快速發展,數據量越來越大,單庫單表逐漸成為瓶頸。所以我們對數據庫進行了水平拆分,將原單庫單表拆分成數據庫分片。
如下圖所示,分庫分表之后,原來在一個數據庫上就能完成的寫操作,可能就會跨多個數據庫,這就產生了跨數據庫事務問題。
1.1.2 業務服務化拆分
在業務發展初期,“一塊大餅”的單業務系統架構,能滿足基本的業務需求。但是隨著業務的快速發展,系統的訪問量和業務復雜程度都在快速增長,單系統架構逐漸成為業務發展瓶頸,解決業務系統的高耦合、可伸縮問題的需求越來越強烈。
如下圖所示,螞蟻金服按照面向服務(SOA)的架構的設計原則,將單業務系統拆分成多個業務系統,降低了各系統之間的耦合度,使不同的業務系統專注于自身業務,更有利于業務的發展和系統容量的伸縮。
業務系統按照服務拆分之后,一個完整的業務往往需要調用多個服務,如何保證多個服務間的數據一致性成為一個難題。
1.2 螞蟻金服遇到的數據一致性問題
在數據庫水平拆分、服務垂直拆分之后,一個業務操作通常要跨多個數據庫、服務才能完成。在分布式網絡環境下,我們無法保障所有服務、數據庫都百分百可用,一定會出現部分服務、數據庫執行成功,另一部分執行失敗的問題。
當出現部分業務操作成功、部分業務操作失敗時,業務數據就會出現不一致。以金融業務中比較常見的“轉賬”場景為例:
如下圖所示,在支付寶的“轉賬”操作中,要分別完成 4 個動作:
創建交易訂單;
創建支付訂單;
A 賬戶扣錢;
B 賬戶加錢;
而完成以上操作要分別訪問 3 個服務和 4 個數據庫。
在分布式環境下,肯定會出現部分操作成功、部分操作失敗的問題,比如:A 賬戶的錢扣了,但是 B 賬戶的錢沒加上,這就造成了資金損失,影響資金安全。
在金融業務場景下,我們必須保證“轉賬”的原子性,要么所有操作全部成功,要么全部失敗,不允許出現部分成功部分失敗的現象。
為了解決跨數據庫、跨服務的業務數據一致性問題,螞蟻金服自主研發了分布式事務中間件。
從 2007 年開始做分布式事務并支持雙十一,至今已經有 12 年。
2013 年,螞蟻金服開始做單元化改造,分布式事務也開始支持 LDC、異地多活和高可用容災,解決了機房故障情況下服務快速恢復的問題。
2014 年,螞蟻金服分布式事務中間件 DTX(Distributed Transaction-eXtended)開始通過螞蟻金融云對外輸出,我們發展了一大批的外部用戶。在發展外部客戶的過程中,外部客戶表示愿意犧牲一部分性能(無螞蟻的業務規模)以換取接入便利性和無侵入性。所以在 2015 年,我們開始做無侵入的事務解決方案:FMT 模式和 XA 模式。
螞蟻金服分布式事務(Distributed Transaction-eXtended,簡稱 DTX)鏈接:
https://tech.antfin.com/products/DTX
二、投入開源社區,共建開源分布式事務?Seata?
2.1 分布式事務 Seata 介紹
Seata(Simple Extensible Autonomous Transaction Architecture,簡單可擴展自治事務框架)是 2019 年 1 月份螞蟻金服和阿里巴巴共同開源的分布式事務解決方案。Seata 開源半年左右,目前已經有接近一萬 star,社區非?;钴S。我們熱忱歡迎大家參與到 Seata 社區建設中,一同將 Seata 打造成開源分布式事務標桿產品。
Seata:https://github.com/seata/seata
2.2 分布式事務 Seata 產品模塊
如下圖所示,Seata 中有三大模塊,分別是 TM、RM 和 TC。其中 TM 和 RM 是作為 Seata 的客戶端與業務系統集成在一起,TC 作為 Seata 的服務端獨立部署。
在 Seata 中,分布式事務的執行流程:
-
TM 開啟分布式事務(TM 向 TC 注冊全局事務記錄);
-
按業務場景,編排數據庫、服務等事務內資源(RM 向 TC 匯報資源準備狀態?);
-
TM 結束分布式事務,事務一階段結束(TM 通知 TC 提交/回滾分布式事務);
-
TC 匯總事務信息,決定分布式事務是提交還是回滾;
-
TC 通知所有 RM 提交/回滾 資源,事務二階段結束。
2.3 分布式事務 Seata 解決方案
Seata 會有 4 種分布式事務解決方案,分別是 AT 模式、TCC 模式、Saga 模式和 XA 模式。
2.3.1 AT 模式
今年 1 月份,Seata 開源了 AT 模式。AT 模式是一種無侵入的分布式事務解決方案。在 AT 模式下,用戶只需關注自己的“業務 SQL”,用戶的 “業務 SQL”?作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作。
AT 模式如何做到對業務的無侵入:
-
一階段:
在一階段,Seata 會攔截“業務 SQL”,首先解析 SQL 語義,找到“業務 SQL”要更新的業務數據,在業務數據被更新前,將其保存成“before image”,然后執行“業務 SQL”更新業務數據,在業務數據更新之后,再將其保存成“after image”,最后生成行鎖。以上操作全部在一個數據庫事務內完成,這樣保證了一階段操作的原子性。
-
二階段提交:
二階段如果是提交的話,因為“業務 SQL”在一階段已經提交至數據庫, 所以 Seata 框架只需將一階段保存的快照數據和行鎖刪掉,完成數據清理即可。
-
二階段回滾:
二階段如果是回滾的話,Seata 就需要回滾一階段已經執行的“業務 SQL”,還原業務數據。回滾方式便是用“before image”還原業務數據;但在還原前要首先要校驗臟寫,對比“數據庫當前業務數據”和 “after image”,如果兩份數據完全一致就說明沒有臟寫,可以還原業務數據,如果不一致就說明有臟寫,出現臟寫就需要轉人工處理。
AT 模式的一階段、二階段提交和回滾均由 Seata 框架自動生成,用戶只需編寫“業務 SQL”,便能輕松接入分布式事務,AT 模式是一種對業務無任何侵入的分布式事務解決方案。
2.3.2 TCC 模式
2019 年 3 月份,Seata 開源了 TCC 模式,該模式由螞蟻金服貢獻。TCC 模式需要用戶根據自己的業務場景實現 Try、Confirm 和 Cancel 三個操作;事務發起方在一階段 執行 Try 方式,在二階段提交執行 Confirm 方法,二階段回滾執行 Cancel 方法。
TCC 三個方法描述:
-
Try:資源的檢測和預留;
-
Confirm:執行的業務操作提交;要求 Try 成功 Confirm 一定要能成功;
-
Cancel:預留資源釋放。
業務模型分 2 階段設計:
用戶接入 TCC ,最重要的是考慮如何將自己的業務模型拆成兩階段來實現。
以“扣錢”場景為例,在接入 TCC 前,對 A 賬戶的扣錢,只需一條更新賬戶余額的 SQL 便能完成;但是在接入 TCC 之后,用戶就需要考慮如何將原來一步就能完成的扣錢操作,拆成兩階段,實現成三個方法,并且保證一階段 Try ?成功的話 二階段 Confirm 一定能成功。
如上圖所示,
Try 方法作為一階段準備方法,需要做資源的檢查和預留。在扣錢場景下,Try 要做的事情是就是檢查賬戶余額是否充足,預留轉賬資金,預留的方式就是凍結 A 賬戶的 轉賬資金。Try 方法執行之后,賬號 A 余額雖然還是 100,但是其中 30 元已經被凍結了,不能被其他事務使用。
二階段 Confirm 方法執行真正的扣錢操作。Confirm 會使用 Try 階段凍結的資金,執行賬號扣款。Confirm 方法執行之后,賬號 A 在一階段中凍結的 30 元已經被扣除,賬號 A 余額變成 70 元 。
如果二階段是回滾的話,就需要在 Cancel 方法內釋放一階段 Try 凍結的 30 元,使賬號 A 的回到初始狀態,100 元全部可用。
用戶接入 TCC 模式,最重要的事情就是考慮如何將業務模型拆成 2 階段,實現成 TCC 的 3 個方法,并且保證 Try 成功 Confirm 一定能成功。相對于 AT 模式,TCC 模式對業務代碼有一定的侵入性,但是 TCC 模式無 AT 模式的全局行鎖,TCC 性能會比 AT 模式高很多。
2.3.3 Saga 模式
Saga 模式是 Seata 即將開源的長事務解決方案,將由螞蟻金服主要貢獻。在 Saga 模式下,分布式事務內有多個參與者,每一個參與者都是一個沖正補償服務,需要用戶根據業務場景實現其正向操作和逆向回滾操作。
分布式事務執行過程中,依次執行各參與者的正向操作,如果所有正向操作均執行成功,那么分布式事務提交。如果任何一個正向操作執行失敗,那么分布式事務會去退回去執行前面各參與者的逆向回滾操作,回滾已提交的參與者,使分布式事務回到初始狀態。
Saga 模式下分布式事務通常是由事件驅動的,各個參與者之間是異步執行的,Saga 模式是一種長事務解決方案。
2.3.4 XA 模式
XA 模式是 Seata 將會開源的另一種無侵入的分布式事務解決方案,任何實現了 XA 協議的數據庫都可以作為資源參與到分布式事務中,目前主流數據庫,例如 MySql、Oracle、DB2、Oceanbase 等均支持 XA 協議。
XA 協議有一系列的指令,分別對應一階段和二階段操作?!皒a start”和 “xa end”用于開啟和結束XA 事務;“xa prepare” 用于預提交 XA 事務,對應一階段準備;“xa commit”和“xa rollback”用于提交、回滾 XA 事務,對應二階段提交和回滾。
在 XA 模式下,每一個 XA 事務都是一個事務參與者。分布式事務開啟之后,首先在一階段執行“xa start”、“業務 SQL”、“xa end”和 “xa prepare” 完成 XA 事務的執行和預提交;二階段如果提交的話就執行 “xa commit”,如果是回滾則執行“xa rollback”。這樣便能保證所有 XA 事務都提交或者都回滾。
XA 模式下,用戶只需關注自己的“業務 SQL”,Seata 框架會自動生成一階段、二階段操作;XA 模式的實現如下:
-
一階段:
在 XA 模式的一階段,Seata 會攔截“業務 SQL”,在“業務 SQL”之前開啟 XA 事務(“xa start”),然后執行“業務 SQL”,結束 XA 事務“xa end”,最后預提交 XA 事務(“xa prepare”),這樣便完成 “業務 SQL”的準備操作。
-
二階段提交:
執行“xa commit”指令,提交 XA 事務,此時“業務 SQL”才算真正的提交至數據庫。
-
二階段回滾:
執行“xa rollback”指令,回滾 XA 事務,完成“業務 SQL”回滾,釋放數據庫鎖資源。
XA 模式下,用戶只需關注“業務 SQL”,Seata 會自動生成一階段、二階段提交和二階段回滾操作。XA 模式和 AT 模式一樣是一種對業務無侵入性的解決方案;但與 AT 模式不同的是,XA 模式將快照數據和行鎖等通過 XA 指令委托給了數據庫來完成,這樣 XA 模式實現更加輕量化。
三、分布式事務在螞蟻金服的實踐
螞蟻金服從 2007 年開始研發和應用分布式事務中間件,用 TCC 模式解決各類金融場景的數據一致性問題,后續又演進出 FMT(AT)、XA、Saga 等模式,各種模式分別適用于各類業務場景。我們決定將螞蟻金服多年的技術積累開源出來,與社區共享螞蟻金服的科技成果。
螞蟻金服內部的分布式事務產品,在實現原理和使用方式上,與 Seata 類似,不同的是,為了支持雙十一,對性能進行了極致優化,為了支持金融系統的高可用容災,借助螞蟻金服三地五中心架構實現了分布式事務服務的高可用容災;接下來主要介紹螞蟻金服在性能優化和高可用容災方面的實踐經驗。
3.1 極致性能優化
3.1.1 同庫模式
通常,一個 TM 會產生一筆主事務日志,一個 RM 會產生一條分支事務日志,每個分布式事務由一個 TM 和若干 RM 組成,一個分布式事務總共會有? 1+N 條事務日志(N 為 RM 個數)。
在默認情況下,分布式事務執行過程中客戶端將事務日志發送給服務端,服務端再將事務日志存儲至數據庫中,一條事務日志的存儲鏈路會有 2 次 TCP ,分別是“客戶端到服務端”和“服務端到數據庫”, 我們稱這種模式為異庫模式。
在異庫模式下,分布式事務存儲事務日志總共需要 2*(1+N) 次左右的 TCP 通信。在 RM 數量較少的業務場景下,分布式事務性能還能接收,但有些業務場景下 RM 數量較多,此時事務內 TCP 數量也會增多,分布式事務性能急劇下降。
在事務執行過程中,客戶端和服務端進行通信的目的是為了存儲事務日志。如果客戶端在存儲事務日志時,繞過服務端直接將事務日志寫入數據庫(如上圖“同庫模式”所示),那么一筆事務日志的存儲鏈路就由原來的 2 次 TCP ?變成只需訪問一次數據庫便可,每條事務日志的存儲減少了一次 TCP 通信,整個分布式事務就減少了 N+2 次 TCP ?請求,分布式事務的性能大幅提升。我們將客戶端直接將事務日志存儲至數據庫的模式稱為同庫模式。
3.1.2 二階段異步執行
通常情況下,分布式事務發起方會依次執行一階段和二階段方法,然后結束分布式事務,返回結果。如果讓分布式事務發起方執行完一階段之后馬上結束并返回結果,二階段交由獨立的線程或者進程異步執行,這樣分布式事務的二階段會晚幾秒鐘或者若干分鐘執行,但事務的最終結果不會有任何改變。
二階段異步執行之后,分布式事務的最終結果不會有任何影響,但是事務發起方要執行的內容減少一半(一階段和二階段都執行變成只執行一階段),直觀的用戶感受是分布式事務的性能提升了 50%。
3.2 分布式事務高可用
為了保障金融系統的高可用,分布式事務服務必須達到 99.99% 的可用率。分布式事務使用了螞蟻金服的三地五中心架構部署,在每個機房都獨立部署分布式事務服務,分布式事務服務是無狀態的,而底層數據庫副本在各機房間也是雙向同步,這樣業務流量從一個機房切到另外一個機房,分布式事務服務不會對業務有任何影響,從而保證了分布式事務服務的高可用。
四、總結
在分布式架構演進中,螞蟻金服對數據庫進了水平拆分,對服務面向功能進行了服務化拆分,從而出現了跨服務、跨數據庫的業務數據一致性挑戰。
?2007 年,螞蟻金服自主研發分布式事務中間件經歷 12 年的嚴苛業務錘煉。2019 年,將多年的技術積累分享給開源分布式事務 Seata,并持續投入社區共建。目前 Seata 提供了 AT、TCC、Saga 和 XA 四種模式,每一種模式分別有各自的應用場景,豐富的解決方案幫助用戶解決給了各類場景的數據一致性問題。
最后一部分,分享了螞蟻金服具體的實踐。為了支持雙十一的高性能需求,對分布式事務進行了極致的性能優化,例如同庫模式、二階段異步執行。為了使金融服務的可用性達到 99.99%,螞蟻金服分布式事務采用三地五中心架構,異地多活的部署模式保障了分布式事務服務的高可用。
相關鏈接:
-
開源分布式事務 Seata:
https://github.com/seata/seata
-
螞蟻金服分布式事務(Distributed Transaction-eXtended)產品鏈接:
https://tech.antfin.com/products/DTX
總結
以上是生活随笔為你收集整理的蚂蚁金服大规模分布式事务实践和开源历程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 眯缝眼怎么改善
- 下一篇: layering-cache