本文整理自螞蟻金服技術專家、分佈式事務 Seata 發起者之一張森(花名:紹輝)在 GIAC 全球互聯網架構大會的分享。詳細講解了在分佈式架構演進中,螞蟻金服面對的跨服務、跨數據庫的業務數據一致性問題以及應對措施,並分享了分佈式事務 Seata 的 AT、TCC、Saga 和 XA 四種模式。
螞蟻金服的業務數據庫起初是單庫單表,但隨着業務數據規模的快速發展,數據量愈來愈大,單庫單表逐漸成爲瓶頸。因此咱們對數據庫進行了水平拆分,將原單庫單表拆分紅數據庫分片。git
以下圖所示,分庫分表以後,原來在一個數據庫上就能完成的寫操做,可能就會跨多個數據庫,這就產生了跨數據庫事務問題。github
在業務發展初期,「一塊大餅」的單業務系統架構,能知足基本的業務需求。可是隨着業務的快速發展,系統的訪問量和業務複雜程度都在快速增加,單系統架構逐漸成爲業務發展瓶頸,解決業務系統的高耦合、可伸縮問題的需求愈來愈強烈。數據庫
以下圖所示,螞蟻金服按照面向服務(SOA)的架構的設計原則,將單業務系統拆分紅多個業務系統,下降了各系統之間的耦合度,使不一樣的業務系統專一於自身業務,更有利於業務的發展和系統容量的伸縮。安全
業務系統按照服務拆分以後,一個完整的業務每每須要調用多個服務,如何保證多個服務間的數據一致性成爲一個難題。
性能優化
在數據庫水平拆分、服務垂直拆分以後,一個業務操做一般要跨多個數據庫、服務才能完成。在分佈式網絡環境下,咱們沒法保障全部服務、數據庫都百分百可用,必定會出現部分服務、數據庫執行成功,另外一部分執行失敗的問題。網絡
當出現部分業務操做成功、部分業務操做失敗時,業務數據就會出現不一致。以金融業務中比較常見的「轉帳」場景爲例:架構
以下圖所示,在支付寶的「轉帳」操做中,要分別完成 4 個動做:框架
1.建立交易訂單;異步
2.建立支付訂單;分佈式
3.A 帳戶扣錢;
4.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(Simple Extensible Autonomous Transaction Architecture,簡單可擴展自治事務框架)是 2019 年 1 月份螞蟻金服和阿里巴巴共同開源的分佈式事務解決方案。Seata 開源半年左右,目前已經有接近一萬 star,社區很是活躍。咱們熱忱歡迎你們參與到 Seata 社區建設中,一同將 Seata 打形成開源分佈式事務標杆產品。
Seata:https://github.com/seata/seata
以下圖所示,Seata 中有三大模塊,分別是 TM、RM 和 TC。其中 TM 和 RM 是做爲 Seata 的客戶端與業務系統集成在一塊兒,TC 做爲 Seata 的服務端獨立部署。
在 Seata 中,分佈式事務的執行流程:
Seata 會有 4 種分佈式事務解決方案,分別是 AT 模式、TCC 模式、Saga 模式和 XA 模式。
今年 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 模式是一種對業務無任何侵入的分佈式事務解決方案。
2019 年 3 月份,Seata 開源了 TCC 模式,該模式由螞蟻金服貢獻。TCC 模式須要用戶根據本身的業務場景實現 Try、Confirm 和 Cancel 三個操做;事務發起方在一階段 執行 Try 方式,在二階段提交執行 Confirm 方法,二階段回滾執行 Cancel 方法。
TCC 三個方法描述:
1.Try:資源的檢測和預留;
2.Confirm:執行的業務操做提交;要求 Try 成功 Confirm 必定要能成功;
3.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 模式高不少。
Saga 模式是 Seata 即將開源的長事務解決方案,將由螞蟻金服主要貢獻。在 Saga 模式下,分佈式事務內有多個參與者,每個參與者都是一個衝正補償服務,須要用戶根據業務場景實現其正向操做和逆向回滾操做。
分佈式事務執行過程當中,依次執行各參與者的正向操做,若是全部正向操做均執行成功,那麼分佈式事務提交。若是任何一個正向操做執行失敗,那麼分佈式事務會去退回去執行前面各參與者的逆向回滾操做,回滾已提交的參與者,使分佈式事務回到初始狀態。
Saga 模式下分佈式事務一般是由事件驅動的,各個參與者之間是異步執行的,Saga 模式是一種長事務解決方案。
XA 模式是 Seata 將會開源的另外一種無侵入的分佈式事務解決方案,任何實現了 XA 協議的數據庫均可以做爲資源參與到分佈式事務中,目前主流數據庫,例如 MySql、Oracle、DB二、Oceanbase 等均支持 XA 協議。
XA 協議有一系列的指令,分別對應一階段和二階段操做。「xa 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 相似,不一樣的是,爲了支持雙十一,對性能進行了極致優化,爲了支持金融系統的高可用容災,藉助螞蟻金服三地五中心架構實現了分佈式事務服務的高可用容災;接下來主要介紹螞蟻金服在性能優化和高可用容災方面的實踐經驗。
一般,一個 TM 會產生一筆主事務日誌,一個 RM 會產生一條分支事務日誌,每一個分佈式事務由一個 TM 和若干 RM 組成,一個分佈式事務總共會有 1+N 條事務日誌(N 爲 RM 個數)。
在默認狀況下,分佈式事務執行過程當中客戶端將事務日誌發送給服務端,服務端再將事務日誌存儲至數據庫中,一條事務日誌的存儲鏈路會有 2 次 TCP ,分別是「客戶端到服務端」和「服務端到數據庫」, 咱們稱這種模式爲異庫模式。
在異庫模式下,分佈式事務存儲事務日誌總共須要 2*(1+N) 次左右的 TCP 通訊。在 RM 數量較少的業務場景下,分佈式事務性能還能接收,但有些業務場景下 RM 數量較多,此時事務內 TCP 數量也會增多,分佈式事務性能急劇降低。
在事務執行過程當中,客戶端和服務端進行通訊的目的是爲了存儲事務日誌。若是客戶端在存儲事務日誌時,繞過服務端直接將事務日誌寫入數據庫(如上圖「同庫模式」所示),那麼一筆事務日誌的存儲鏈路就由原來的 2 次 TCP 變成只需訪問一次數據庫即可,每條事務日誌的存儲減小了一次 TCP 通訊,整個分佈式事務就減小了 N+2 次 TCP 請求,分佈式事務的性能大幅提高。咱們將客戶端直接將事務日誌存儲至數據庫的模式稱爲同庫模式。
一般狀況下,分佈式事務發起方會依次執行一階段和二階段方法,而後結束分佈式事務,返回結果。若是讓分佈式事務發起方執行完一階段以後立刻結束並返回結果,二階段交由獨立的線程或者進程異步執行,這樣分佈式事務的二階段會晚幾秒鐘或者若干分鐘執行,但事務的最終結果不會有任何改變。
二階段異步執行以後,分佈式事務的最終結果不會有任何影響,可是事務發起方要執行的內容減小一半(一階段和二階段都執行變成只執行一階段),直觀的用戶感覺是分佈式事務的性能提高了 50%。
爲了保障金融系統的高可用,分佈式事務服務必須達到 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