分佈式事務--Fescar

地址:https://github.com/alibaba/fescar

《分佈式事物--GTS的原理、架構與特點》

《Fescar源碼學習--事物管理者TM(服務調用方)》

《Fescar源碼學習--資源管理者RM(服務提供方)》

《Fescar源碼學習--服務協調器(TC)》

Fescar 是 阿里巴巴 開源的 分佈式事務中間件,以 高效 並且對業務 0 侵入 的方式,解決 微服務 場景下面臨的分佈式事務問題。

1. 什麼是微服務化帶來的分佈式事務問題?

首先,設想一個傳統的單體應用(Monolithic App),通過 3 個 Module,在同一個數據源上更新數據來完成一項業務。

很自然的,整個業務過程的數據一致性由本地事務來保證。

Monolithic architecture

隨着業務需求和架構的變化,單體應用被拆分爲微服務:原來的 3 個 Module 被拆分爲 3 個獨立的服務,分別使用獨立的數據源(Pattern: Database per service)。業務過程將由 3 個服務的調用來完成。

Microservices architecture

此時,每一個服務內部的數據一致性仍由本地事務來保證。而整個業務層面的全局數據一致性要如何保障呢?這就是微服務架構下面臨的,典型的分佈式事務需求:我們需要一個分佈式事務的解決方案保障業務全局的數據一致性。

Fescar Solution

2. Fescar 的發展歷程

阿里是國內最早一批進行應用分佈式(微服務化)改造的企業,所以很早就遇到微服務架構下的分佈式事務問題。

2014 年,阿里中間件團隊發佈 TXC(Taobao Transaction Constructor),爲集團內應用提供分佈式事務服務。

2016 年,TXC 經過產品化改造,以 GTS(Global Transaction Service) 的身份登陸阿里雲,成爲當時業界唯一一款雲上分佈式事務產品,在阿雲裏的公有云、專有云解決方案中,開始服務於衆多外部客戶。

2019 年起,基於 TXC 和 GTS 的技術積累,阿里中間件團隊發起了開源項目 Fescar(Fast & EaSy Commit And Rollback, FESCAR),和社區一起建設這個分佈式事務解決方案。

TXC/GTS/Fescar 一脈相承,爲解決微服務架構下的分佈式事務問題交出了一份與衆不同的答卷。

2.1 設計初衷

高速增長的互聯網時代,快速試錯 的能力對業務來說是至關重要的:

  • 一方面,不應該因爲技術架構上的微服務化和分佈式事務支持的引入,給業務層面帶來額外的研發負擔。
  • 另一方面,引入分佈式事務支持的業務應該基本保持在同一量級上的性能表現,不能因爲事務機制顯著拖慢業務。

基於這兩點,我們設計之初的最重要的考量就在於:

  • 對業務無侵入: 這裏的 侵入 是指,因爲分佈式事務這個技術問題的制約,要求應用在業務層面進行設計和改造。這種設計和改造往往會給應用帶來很高的研發和維護成本。我們希望把分佈式事務問題在 中間件 這個層次解決掉,不要求應用在業務層面做額外的工作。
  • 高性能: 引入分佈式事務的保障,必然會有額外的開銷,引起性能的下降。我們希望把分佈式事務引入的性能損耗降到非常低的水平,讓應用不因爲分佈式事務的引入導致業務的可用性受影響。

2.2 既有的解決方案爲什麼不滿足?

既有的分佈式事務解決方案按照對業務侵入性分爲兩類,即:對業務無侵入的和對業務有侵入的。

業務無侵入的方案

既有的主流分佈式事務解決方案中,對業務無侵入的只有基於 XA 的方案,但應用 XA 方案存在 3 個方面的問題:

  1. 要求數據庫提供對 XA 的支持。如果遇到不支持 XA(或支持得不好,比如 MySQL 5.7 以前的版本)的數據庫,則不能使用。
  2. 受協議本身的約束,事務資源(數據記錄、數據庫連接)的鎖定週期長。長週期的資源鎖定從業務層面來看,往往是不必要的,而因爲事務資源的管理器是數據庫本身,應用層無法插手。這樣形成的局面就是,基於 XA 的應用往往性能會比較差,而且很難優化。
  3. 已經落地的基於 XA 的分佈式解決方案,都依託於重量級的應用服務器(Tuxedo/WebLogic/WebSphere 等),這是不適用於微服務架構的。

侵入業務的方案

實際上,最初分佈式事務只有 XA 這個唯一方案。XA 是完備的,但在實踐過程中,由於種種原因(包含但不限於上面提到的 3 點)往往不得不放棄,轉而從業務層面着手來解決分佈式事務問題。比如:

  • 基於可靠消息的最終一致性方案
  • TCC
  • Saga

都屬於這一類。這些方案的具體機制在這裏不做展開,網上這方面的論述文章非常多。總之,這些方案都要求在應用的業務層面把分佈式事務技術約束考慮到設計中,通常每一個服務都需要設計實現正向和反向的冪等接口。這樣的設計約束,往往會導致很高的研發和維護成本。

2.3 理想的方案應該是什麼樣子?

不可否認,侵入業務的分佈式事務方案都經過大量實踐驗證,能有效解決問題,在各行各業的業務應用系統中起着重要作用。但回到原點來思考,這些方案的採用實際上都是 迫於無奈。設想,如果基於 XA 的方案能夠不那麼 ,並且能保證業務的性能需求,相信不會有人願意把分佈式事務問題拿到業務層面來解決。

一個理想的分佈式事務解決方案應該:像使用 本地事務 一樣簡單,業務邏輯只關注業務層面的需求,不需要考慮事務機制上的約束。

3. 原理和設計

我們要設計一個對業務無侵入的方案,所以從業務無侵入的 XA 方案來思考:

是否可以在 XA 的基礎上演進,解決掉 XA 方案面臨的問題呢?

3.1 如何定義一個分佈式事務?

首先,很自然的,我們可以把一個分佈式事務理解成一個包含了若干 分支事務 的 全局事務全局事務 的職責是協調其下管轄的 分支事務 達成一致,要麼一起成功提交,要麼一起失敗回滾。此外,通常 分支事務 本身就是一個滿足 ACID 的 本地事務。這是我們對分佈式事務結構的基本認識,與 XA 是一致的。

Global & Branch Transaction

其次,與 XA 的模型類似,我們定義 3 個組件來協議分佈式事務的處理過程。

FESCAR Model

  • Transaction Coordinator (TC): 事務協調器,維護全局事務的運行狀態,負責協調並驅動全局事務的提交或回滾。
  • Transaction Manager (TM): 控制全局事務的邊界,負責開啓一個全局事務,並最終發起全局提交或全局回滾的決議。
  • Resource Manager (RM): 控制分支事務,負責分支註冊、狀態彙報,並接收事務協調器的指令,驅動分支(本地)事務的提交和回滾。

一個典型的分佈式事務過程:

  1. TM 向 TC 申請開啓一個全局事務,全局事務創建成功並生成一個全局唯一的 XID。
  2. XID 在微服務調用鏈路的上下文中傳播。
  3. RM 向 TC 註冊分支事務,將其納入 XID 對應全局事務的管轄。
  4. TM 向 TC 發起針對 XID 的全局提交或回滾決議。
  5. TC 調度 XID 下管轄的全部分支事務完成提交或回滾請求。

Architecture

至此,Fescar 的協議機制總體上看與 XA 是一致的。

3.2 與 XA 的差別在什麼地方?

架構層次

RM in Architecture

XA 方案的 RM 實際上是在數據庫層,RM 本質上就是數據庫自身(通過提供支持 XA 的驅動程序來供應用使用)。

而 Fescar 的 RM 是以二方包的形式作爲中間件層部署在應用程序這一側的,不依賴與數據庫本身對協議的支持,當然也不需要數據庫支持 XA 協議。這點對於微服務化的架構來說是非常重要的:應用層不需要爲本地事務和分佈式事務兩類不同場景來適配兩套不同的數據庫驅動。

這個設計,剝離了分佈式事務方案對數據庫在 協議支持 上的要求。

兩階段提交

先來看一下 XA 的 2PC 過程。

XA-2PC

無論 Phase2 的決議是 commit 還是 rollback,事務性資源的鎖都要保持到 Phase2 完成才釋放。

設想一個正常運行的業務,大概率是 90% 以上的事務最終應該是成功提交的,我們是否可以在 Phase1 就將本地事務提交呢?這樣 90% 以上的情況下,可以省去 Phase2 持鎖的時間,整體提高效率。

FESCAR-2PC

  • 分支事務中數據的 本地鎖 由本地事務管理,在分支事務 Phase1 結束時釋放。
  • 同時,隨着本地事務結束,連接 也得以釋放。
  • 分支事務中數據的 全局鎖 在事務協調器側管理,在決議 Phase2 全局提交時,全局鎖馬上可以釋放。只有在決議全局回滾的情況下,全局鎖 才被持有至分支的 Phase2 結束。

這個設計,極大地減少了分支事務對資源(數據和連接)的鎖定時間,給整體併發和吞吐的提升提供了基礎。

當然,你肯定會問:Phase1 即提交的情況下,Phase2 如何回滾呢?

3.3 分支事務如何提交和回滾?

首先,應用需要使用 Fescar 的 JDBC 數據源代理,也就是 Fescar 的 RM。

Data Source Proxy

Phase1:

Fescar 的 JDBC 數據源代理通過對業務 SQL 的解析,把業務數據在更新前後的數據鏡像組織成回滾日誌,利用 本地事務 的 ACID 特性,將業務數據的更新和回滾日誌的寫入在同一個 本地事務 中提交。

這樣,可以保證:任何提交的業務數據的更新一定有相應的回滾日誌存在。

Branch Transaction with UNDO LOG

基於這樣的機制,分支的本地事務便可以在全局事務的 Phase1 提交,馬上釋放本地事務鎖定的資源。

Phase2:

  • 如果決議是全局提交,此時分支事務此時已經完成提交,不需要同步協調處理(只需要異步清理回滾日誌),Phase2 可以非常快速地完成。

Global Commit

  • 如果決議是全局回滾,RM 收到協調器發來的回滾請求,通過 XID 和 Branch ID 找到相應的回滾日誌記錄,通過回滾記錄生成反向的更新 SQL 並執行,以完成分支的回滾。

Global Rollback

3.4 事務傳播機制

XID 是一個全局事務的唯一標識,事務傳播機制要做的就是把 XID 在服務調用鏈路中傳遞下去,並綁定到服務的事務上下文中,這樣,服務鏈路中的數據庫更新操作,就都會向該 XID 代表的全局事務註冊分支,納入同一個全局事務的管轄。

基於這個機制,Fescar 是可以支持任何微服務 RPC 框架的。只要在特定框架中找到可以透明傳播 XID 的機制即可,比如,Dubbo 的 Filter + RpcContext。

對應到 Java EE 規範和 Spring 定義的事務傳播屬性,Fescar 的支持如下:

  • PROPAGATION_REQUIRED: 默認支持
  • PROPAGATION_SUPPORTS: 默認支持
  • PROPAGATION_MANDATORY:應用通過 API 來實現
  • PROPAGATION_REQUIRES_NEW:應用通過 API 來實現
  • PROPAGATION_NOT_SUPPORTED:應用通過 API 來實現
  • PROPAGATION_NEVER:應用通過 API 來實現
  • PROPAGATION_REQUIRED_NESTED:不支持

3.5 隔離性

全局事務的隔離性是建立在分支事務的本地隔離級別基礎之上的。

在數據庫本地隔離級別 讀已提交 或以上的前提下,Fescar 設計了由事務協調器維護的 全局寫排他鎖,來保證事務間的 寫隔離,將全局事務默認定義在 讀未提交 的隔離級別上。

我們對隔離級別的共識是:絕大部分應用在 讀已提交 的隔離級別下工作是沒有問題的。而實際上,這當中又有絕大多數的應用場景,實際上工作在 讀未提交 的隔離級別下同樣沒有問題。

在極端場景下,應用如果需要達到全局的 讀已提交,Fescar 也提供了相應的機制來達到目的。默認,Fescar 是工作在 讀無提交 的隔離級別下,保證絕大多數場景的高效性。

Isolation

事務的 ACID 屬性在 Fescar 中的體現是一個比較複雜的話題,我們會有專門的文章來深入分析,這裏不做進一步展開。

4. 適用場景分析

前文所述的 Fescar 的核心原理中有一個 重要前提:分支事務中涉及的資源,必須 是支持 ACID 事務的 關係型數據庫。分支的提交和回滾機制,都依賴於本地事務的保障。所以,如果應用使用的數據庫是不支持事務的,或根本不是關係型數據庫,就不適用。

另外,目前 Fescar 的實現還存在一些侷限,比如:事務隔離級別最高支持到 讀已提交 的水平,SQL 的解析還不能涵蓋全部的語法等。

爲了覆蓋 Fescar 原生機制暫時不能支持應用場景,我們定義了另外一種工作模式。

上面介紹的 Fescar 原生工作模式稱爲 AT(Automatic Transaction)模式,這種模式是對業務無侵入的。與之相應的另外一種工作模式稱爲 MT(Manual Transaction)模式,這種模式下,分支事務需要應用自己來定義業務本身及提交和回滾的邏輯。

4.1 分支的基本行爲模式

作爲全局事務一部分的分支事務,除本身的業務邏輯外,都包含 4 個與協調器交互的行爲:

  • 分支註冊: 在分支事務的數據操作進行之前,需要向協調器註冊,把即將進行的分支事務數據操作,納入一個已經開啓的全局事務的管理中去,在分支註冊成功後,纔可以進行數據操作。
  • 狀態上報: 在分支事務的數據操作完成後,需要向事務協調器上報其執行結果。
  • 分支提交:響應協調器發出的分支事務提交的請求,完成分支提交。
  • 分支回滾:響應協調器發出的分支事務回滾的請求,完成分支回滾。

How does RM talk to TC

4.2 AT 模式分支的行爲模式

業務邏輯不需要關注事務機制,分支與全局事務的交互過程自動進行。

AT branch

4.3 MT 模式分支的行爲模式

業務邏輯需要被分解爲 Prepare/Commit/Rollback 3 部分,形成一個 MT 分支,加入全局事務。

MT branch

MT 模式一方面是 AT 模式的補充。另外,更重要的價值在於,通過 MT 模式可以把衆多非事務性資源納入全局事務的管理中。

4.4 混合模式

因爲 AT 和 MT 模式的分支從根本上行爲模式是一致的,所以可以完全兼容,即,一個全局事務中,可以同時存在 AT 和 MT 的分支。這樣就可以達到全面覆蓋業務場景的目的:AT 模式可以支持的,使用 AT 模式;AT 模式暫時支持不了的,用 MT 模式來替代。另外,自然的,MT 模式管理的非事務性資源也可以和支持事務的關係型數據庫資源一起,納入同一個分佈式事務的管理中。

4.5 應用場景的遠景

回到我們設計的初衷:一個理想的分佈式事務解決方案是不應該侵入業務的。MT 模式是在 AT 模式暫時不能完全覆蓋所有場景的情況下,一個比較自然的補充方案。我們希望通過 AT 模式的不斷演進增強,逐步擴大所支持的場景,MT 模式逐步收斂。未來,我們會納入對 XA 的原生支持,用 XA 這種無侵入的方式來覆蓋 AT 模式無法觸達的場景。

Roadmap of Transaction Mode

5. 擴展點

5.1 微服務框架的支持

事務上下文在微服務間的傳播需要根據微服務框架本身的機制,訂製最優的,對應用層透明的解決方案。有興趣在這方面共建的開發者可以參考內置的對 Dubbo 的支持方案,來實現對其他微服務框架的支持。

5.2 所支持的數據庫類型

因爲 AT 涉及 SQL 的解析,所以在不同類型的數據庫上工作,會有一些特定的適配。有興趣在這方面共建的開發者可以參考內置的對 MySQL 的支持方案,來實現對其他數據庫的支持。

5.3 配置和服務註冊發現

支持接入不同的配置和服務註冊發現解決方案。比如:Nacos、Eureka、ZooKeeper 等。

5.4 MT 模式的場景拓展

MT 模式的一個重要作用就是,可以把非關係型數據庫的資源,通過 MT 模式分支的包裝,納入到全局事務的管轄中來。比如,Redis、HBase、RocketMQ 的事務消息等。有興趣在這方面共建的開發者可以在這裏貢獻一系列相關生態的適配方案。

5.5 事務協調器的分佈式高可用方案

針對不同場景,支持不同的方式作爲事務協調器 Server 端的高可用方案。比如,針對事務狀態的持久化,可以是基於文件的實現方案,也可以是基於數據庫的實現方案;集羣間的狀態同步,可以是基於 RPC 通信的方案,也可以是基於高可用 KV 存儲的方案。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章