上周,分布式事務 Fescar 宣布進行品牌更新:
Thanks, Fescar ️,
Hello, Seata 。
Seata 意為:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事務解決方案。
項目位址:
https://github.com/seata/seata螞蟻金服在 Seata 0.4.0 版本加入了 TCC 模式,後續也會持續輸入。
為了幫助大家了解,分布式事務開源負責人紹輝進行了一次線下分享,詳細講述了分布式事務在螞蟻金服的發展,希望可以幫助大家了解分布式事務,以下為分享的文字整理版本。
前言
今天的分享将從以下三個部分展開:分布式事務問題産生的背景、螞蟻金服分布式事務以及分布式事務 Seata 的 Roadmap。
分享嘉賓:紹輝 螞蟻金服 分布式事務開源負責人
1、分布式事務問題産生的背景
1.1、資料庫的水準拆分
螞蟻金服早期,業務量比較小,單庫單表便能滿足業務需求;但是随着業務的發展,單庫單表資料庫逐漸成為瓶頸。為了解決資料庫的瓶頸問題,我們對資料庫進行了水準拆分。拆分所帶來的一個問題就是以前一個資料庫上便能完成的寫操作現在要跨多個資料庫,由此帶來了跨庫事務問題。
1.2、業務的服務化拆分
螞蟻金服早期是單系統架構,所有業務服務幾乎都在少數幾個 APP 中。随着業務的發展,業務越來越複雜,服務之間的耦合度也越來越高,故我們對系統進行了重構,服務按照功能進行解耦和垂直拆分。拆分之後所帶來的問題就是一個業務活動原來隻需要調用一個服務就能完成,現在需要調用多個服務才能完成,由此産生了跨服務事務問題。
1.3、轉賬案例說明資料一緻性問題
資料庫的水分拆分以及服務的垂直拆分,所帶來的問題是一個業務活動通常要調用多個服務、通路多個資料庫才能完成。
以金融業務場景下的轉賬場景為例,轉賬服務要完成以下操作:
- 調用交易系統服務建立交易訂單;
- 調用支付系統記錄支付明細;
- 調用賬務系統執行 A 扣錢;
- 調用賬務系統執行 B 加錢。
以上 4 個操作要跨 3 個系統,通路 4 個資料庫。而網絡、資料庫、機器等都具有不可靠性,我們很難保證以上 4 個操作能 100% 全部成功。
在金融屬性的業務中,不允許 A 賬戶的錢扣了,而 B 賬戶的錢沒有加上的現象出現,是以我們必須想辦法保證 1 ~ 4 這四個操作要麼全部成功,要麼全部失敗;是以螞蟻金服自主研發了分布式事務中間件,解決跨服務、跨資料庫的資料一緻性問題。
2、螞蟻金服分布式事務
2.1、分布式事務理論基礎
在介紹螞蟻金服的分布式事務中間件之前,先介紹一些分布式事務的理論背景。
- 2PC
兩階段送出協定(Two Phase Commitment Protocol)是分布式事務最基本的協定。在兩階段送出協定中,有一個事務管理器和多個資料總管,事務管理器分兩階段協調資料總管。在第一階段,事務管理器詢問所有資料總管準備是否成功。如果所有資源均準備成功,那麼在第二階段事務管理器會要求所有資料總管執行送出操作;如果任一資料總管在第一階段傳回準備失敗,那麼事務管理器會要求所有資料總管在第二階段執行復原操作。通過事務管理器的兩階段協調,最終所有資料總管要麼全部送出,要麼全部復原,最終狀态都是一緻的。
- TCC
資料總管有很多實作方式,其中 TCC(Try-Confirm-Cancel)是資料總管的一種服務化的實作。TCC 是一種比較成熟的分布式事務解決方案,可用于解決跨資料庫、跨服務業務操作的資料一緻性問題。TCC 其 Try、Confirm、Cancel 3 個方法均由業務編碼實作,故 TCC 可以被稱為是服務化的資料總管。
TCC 的 Try 操作作為一階段,負責資源的檢查和預留;Confirm 操作作為二階段送出操作,執行真正的業務;Cancel 是二階段復原操作,執行預留資源的取消,使資源回到初始狀态。
如下圖所示,使用者實作 TCC 服務之後,該 TCC 服務将作為分布式事務的其中一個資源,參與到整個分布式事務中。事務管理器分兩個階段協調 TCC 服務,在第一階段調用所有 TCC 服務的 Try 方法,在第二階段執行所有 TCC 服務的 Confirm 或者 Cancel 方法,最終所有 TCC 服務要麼全部都是送出的、要麼全部都是復原的。
2.2、螞蟻金服分布式産品介紹
螞蟻金服從 2007 年開始做分布式事務,至今已經有 12 年曆史。螞蟻金服的分布式事務最初是采用 TCC 實作的,TCC 模式幫螞蟻業務解決了各類金融核心場景下的資料一緻性問題。
2007 年我們開始支援雙十一,為了滿足雙十一的高性能需求,我們對分布式事務做了一系列的性能優化。
2013年,螞蟻金服開始做單元化改造,分布式事務也開始支援 LDC、異地多活和高可用容災,解決了機房故障情況下服務快速恢複的問題。
2014年,螞蟻金服分布式事務中間件開始通過螞蟻金融雲對外輸出,我們發展了一大批的外部使用者;在發展外部客戶的過程中,外部客戶表示願意犧牲一部分性能(無螞蟻的業務規模)以換取接入便利性和無侵入性。
是以在 2015年,我們開始做無侵入的事務解決方案:FMT 模式和 XA 模式。
螞蟻金服分布式事務中間件經過長期演進,目前積累了 TCC、FMT 和 XA 三種模式,具有豐富的應用場景。下面分别介紹這三種模式。
2.3、TCC 模式
螞蟻金服的 TCC 模式和前面介紹 TCC 理論中提的 TCC 原理是一緻的。不同的是,我們在整個分布式事務執行過程中,會去記錄事務日志,一個分布式事務會産生一條主事務記錄(對應發起方)和若幹分支事務記錄(對應 TCC 參與者)。記錄事務日志的目的是,當分布式事務執行過程中出現異常中斷時,事務恢複服務通過輪詢事務日志,找出這個異常中斷的事務,補償執行該異常事務剩餘未完成的動作,整個分布式事務的最終狀态要麼全部送出,要麼全部復原。
TCC 設計規範和注意事項:
使用者在接入 TCC 時,大部分工作都集中在如何實作 TCC 服務上。經過螞蟻金服多年的 TCC 應用實踐,總結如下在 TCC 設計和實作過程中的注意事項:
1、業務操作分兩階段完成:
接入 TCC 前,業務操作隻需要一步就能完成。但是在接入 TCC 之後,需要考慮如何将其分成兩個階段完成:把資源的檢查和預留放在一階段的 Try 操作中進行,把真正的業務操作的執行放在二階段的 Confirm 操作中進行。
以下舉例說明業務模式如何分成兩階段進行設計,舉例場景:“賬戶 A 的餘額中有 100 元,需要扣除其中 30 元”。
在接入 TCC 之前,使用者編寫 SQL:“update 賬戶表 set 餘額 = 餘額 -20 where 賬戶 = A”,便能一步完成扣款操作。
在接入 TCC 之後,就需要考慮如何将扣款操作分成兩步完成:
- Try 操作:資源的檢查和預留。
在扣款場景,Try 操作要做的事情就是先檢查 A 賬戶餘額是否足夠,再當機要扣款的 30 元(預留資源);此階段不會發生真正的扣款。
- Confirm 操作:執行真正業務的送出。
在扣款場景下,Confirm 階段做的事情就是發生真正的扣款,把 A 賬戶中已經當機的 30 元錢扣掉。
- Cancel 操作:預留資源的釋放。
在扣款場景下,扣款取消,Cancel 操作執行的任務是釋放 Try 操作當機的 30 元錢,使 A 賬戶回到初始狀态。
2、并發控制
使用者在實作 TCC 時,應當考慮并發性問題,将鎖的粒度降到最低,以最大限度提高分布式事務的并發性。
以下還是以 A 賬戶扣款為例,“賬戶 A 上有 100 元,事務 T1 要扣除其中的 30 元,事務 T2 也要扣除 30 元,出現并發”。
在一階段 Try 操作中,分布式事務 T1 和分布式事務 T2 分别當機資金的那一部分資金,互相之間無幹擾。這樣在分布式事務的二階段,無論 T1 是送出還是復原,都不會對 T2 産生影響,這樣 T1 和 T2 可以在同一筆業務資料上并行執行。
3、允許空復原
如下圖所示,事務協調器在調用 TCC 服務的一階段 Try 操作時,可能會出現因為丢包而導緻的網絡逾時。此時事務管理器會觸發二階段復原,調用 TCC 服務的 Cancel 操作,而 Cancel 操作調用未出現逾時。
TCC 服務在未收到 Try 請求的情況下收到 Cancel 請求,這種場景被稱為空復原。空復原在生産環境經常出現,使用者在實作 TCC 服務時,應允許空復原的執行,即收到空復原時傳回成功。
4、防懸挂控制
如下圖所示,事務協調器在調用 TCC 服務的一階段 Try 操作時,可能會出現因網絡擁堵而導緻的逾時。此時事務管理器會觸發二階段復原,調用 TCC 服務的 Cancel 操作,Cancel 調用未逾時。在此之後,擁堵在網絡上的一階段 Try 資料包被 TCC 服務收到,出現二階段 Cancel 請求比一階段 Try 請求先執行的情況,此 TCC 服務在執行晚到的 Try 之後,将永遠不會再收到二階段的 Confirm 或者 Cancel,造成 TCC 服務懸挂。
使用者在實作 TCC 服務時,要允許空復原,但是要拒絕執行空復原之後 Try 請求,要避免出現懸挂;
5、幂等控制
無論是網絡資料包重傳,還是異常事務的補償執行,都會導緻 TCC 服務的 Try、Confirm 或者 Cancel 操作被重複執行;使用者在實作 TCC 服務時,需要考慮幂等控制,即 Try、Confirm、Cancel 執行一次和執行多次的業務結果是一樣的。
2.4、FMT 模式
FMT(Framework-managed transaction)架構管理事務,是一種無侵入的事務解決方案。該模式下,分布式事務架構會托管所有的事務操作,事務的一階段和二階段操作均由架構自動生成,使用者 SQL 将作為分布式事務的一階段,而二階段由架構自動生成“送出/復原”操作。
1、FMT 一階段
FMT 的一階段是分布式事務架構自動生成的,分布式事務架構會在一階段攔截業務的 SQL 語句,在業務執行前,将業務 SQL 修改前的資料儲存成原快照(undo log);在業務 SQL 執行之後,将更新的業務資料儲存成新快照(redo log),最後用表名+主鍵值的方式生成行鎖,來做分布式事務的并發控制。
解析 SQL 語義的目的是為了便于找到業務要更新的業務資料;而提取表中繼資料的目的為了找到業務表的主鍵和唯一性限制鍵,便于生成行鎖。
2、FMT 二階段
FMT 模式下,一階段主要是為了保持 undo log、redo log 等中間資料,保持這些中間資料的目的是為了生成二階段的操作。
- FTM 二階段送出
二階段送出操作是自動生成的,由于業務 SQL 在一階段已經送出至資料庫,故二階段送出隻需删除一階段儲存的中間資料(undo log、redo log和行鎖)。
- FMT 二階段復原
二階段復原操作也是自動生成的,目的是使用 undo log 復原一階段業務 SQL 更新的業務資料。具體操作步驟是:
首先,需要校驗髒寫。校驗髒寫的方式使用 redo log 與資料庫目前值進行對比,如果兩份資料完全一緻則說明沒有出現髒寫,如果兩份資料不一緻,則說明出現髒寫;如果出現髒寫,就需要轉人工處理,不能再使用 undo log 復原業務資料。
然後,還原業務資料。如果未出現髒寫,則使用 undo log 復原業務資料,使業務資料恢複到初始的值。
最後,删除中間資料。業務資料還原之後,便可以将中間資料(undo log、redo log和行鎖)全部删掉,完成復原操作。
2.5、XA 模式
XA 模式是另外一種無侵入的分布式事務解決方案,不同于 FMT 的是,XA 模式下,所有一階段和二階段都由資料庫來完成。螞蟻分布式事務架構在一階段調用資料的一階段 XA 接口(xa prepare),在二階段調用資料的二階段 XA 接口(xa commit/xa rollback)。
XA 模式有以下特點:
- 主流的資料庫均支援 XA 寫,覆寫面廣;
- 與螞蟻自研資料庫 Oceanbase 深度定制,解決 XA 事務性能問題;
- 借助資料庫的 MVCC 特性,實作了分布式 MVCC 和全局一緻性讀。
3、螞蟻金服投入分布式事務 Seata 社群共建
2019 年 1 月,基于技術積累,阿裡巴巴中間件團隊發起了開源項目 Fescar(Fast & EaSy Commit And Rollback, Fescar),和社群一起共建分布式事務解決方案。Fescar 為解決微服務架構下的分布式事務問題交出了一份與衆不同的答卷。而 Fescar 的願景是讓分布式事務的使用像本地事務的使用一樣簡單和高效。最終的目标是希望可以讓 Fescar 适用于所有的分布式事務場景。
為了達到适用于更多的分布式事務業務場景的目标,螞蟻金服加入 Fescar 社群共建,加入了 TCC 模式。
螞蟻金服的加入引發了社群核心成員的讨論,為了達到适用于所有的分布式事務業務場景的目标,也為了社群更中立、更開放、生态更加豐富,社群核心成員們決定進行品牌更新,改名 Seata。Seata 意為:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事務解決方案。
自開源以來,Seata 一直受益于社群的貢獻。截止目前,分布式事務 Seata 已經擁有超過 7000 的 Star ,超 55 位 Contributors,開發者們的加入,使得社群的生态更加豐富也更有活力。
2019 年 5 月,Seata 将加入服務端 HA 叢集支援,從此,Seata 可以達到生産環境使用的标準。
歡迎對分布式事務有熱情的開發者們加入社群的共建中來,為 Seata 帶來更多的想象空間。
總結
- 現場視訊以及詳細 PPT 回顧位址: https://tech.antfin.com/activities/382
- GitHub 位址: