歡迎光臨
每天分享高質量文章

螞蟻金服分佈式事務開源以及實踐 | SOFA 開源一周年獻禮

上周,分佈式事務 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 地址:

    https://github.com/seata/seata

    赞(0)

    分享創造快樂