微服務倡導將複雜的單體應用拆分爲若干個功能簡單、鬆耦合的服務,這樣能夠下降開發難度、加強擴展性、便於敏捷開發。當前被愈來愈多的開發者推崇,系統微服務化後,一個看似簡單的功能,內部可能須要調用多個服務並操做多個數據庫實現,服務調用的分佈式事務問題變的很是突出。分佈式事務已經成爲微服務落地最大的阻礙,也是最具挑戰性的一個技術難題。java
首先,設想一個傳統的單體應用(Monolithic App),經過 3 個 Module,在同一個數據源上更新數據來完成一項業務。數據庫
很天然的,整個業務過程的數據一致性由本地事務來保證。服務器
隨着業務需求和架構的變化,單體應用被拆分爲微服務:原來的 3 個 Module 被拆分爲 3 個獨立的服務,分別使用獨立的數據源(Pattern: Database per service)。業務過程將由 3 個服務的調用來完成。架構
此時,每個服務內部的數據一致性仍有本地事務來保證。而整個業務層面的全局數據一致性要如何保障呢?這就是微服務架構下面臨的,典型的分佈式事務需求:咱們須要一個分佈式事務的解決方案保障業務全局的數據一致性。併發
阿里是國內最先一批進行應用分佈式(微服務化)改造的企業,因此很早就遇到微服務架構下的分佈式事務問題。框架
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 個方面的問題:
實際上,最初分佈式事務只有 XA 這個惟一方案。XA 是完備的,但在實踐過程當中,因爲種種緣由(包含但不限於上面提到的 3 點)每每不得不放棄,轉而從業務層面着手來解決分佈式事務問題。好比:
都屬於這一類。這些方案的具體機制在這裏不作展開,網上這方面的論述文章很是多。總之,這些方案都要求在應用的業務層面把分佈式事務技術約束考慮到設計中,一般每個服務都須要設計實現正向和反向的冪等接口。這樣的設計約束,每每會致使很高的研發和維護成本。
2.3 理想的方案應該是什麼樣子?
不能否認,侵入業務的分佈式事務方案都通過大量實踐驗證,能有效解決問題,在各類行業的業務應用系統中起着重要做用。但回到原點來思考,這些方案的採用實際上都是迫於無奈。設想,若是基於 XA 的方案可以不那麼重,而且能保證業務的性能需求,相信不會有人願意把分佈式事務問題拿到業務層面來解決。
一個理想的分佈式事務解決方案應該:像使用本地事務同樣簡單,業務邏輯只關注業務層面的需求,不須要考慮事務機制上的約束。
咱們要設計一個對業務無侵入的方案,因此從業務無侵入的 XA 方案來思考:是否能夠在 XA 的基礎上演進,解決掉 XA 方案面臨的問題呢?
3.1 如何定義一個分佈式事務?
首先,很天然的,咱們能夠把一個分佈式事務理解成一個包含了若干分支事務的全局事務。全局事務的職責是協調其下管轄的 分支事務 達成一致,要麼一塊兒成功提交,要麼一塊兒失敗回滾。此外,一般分支事務自己就是一個知足 ACID 的本地事務。這是咱們對分佈式事務結構的基本認識,與 XA 是一致的。
其次,與 XA 的模型相似,咱們定義 3 個組件來協議分佈式事務的處理過程。
一個典型的分佈式事務過程:
至此,Fescar 的協議機制整體上看與 XA 是一致的。
3.2 與 XA 的差異在什麼地方?
架構層次
XA 方案的 RM 其實是在數據庫層,RM 本質上就是數據庫自身(經過提供支持 XA 的驅動程序來供應用使用)。
而 Fescar 的 RM 是以二方包的形式做爲中間件層部署在應用程序這一側的,不依賴與數據庫自己對協議的支持,固然也不須要數據庫支持 XA 協議。這點對於微服務化的架構來講是很是重要的:應用層不須要爲本地事務和分佈式事務兩類不一樣場景來適配兩套不一樣的數據庫驅動。
這個設計,剝離了分佈式事務方案對數據庫在 協議支持 上的要求。
兩階段提交
先來看一下 XA 的 2PC 過程。
不管 Phase2 的決議是 commit 仍是 rollback,事務性資源的鎖都要保持到 Phase2 完成才釋放。
設想一個正常運行的業務,大機率是 90% 以上的事務最終應該是成功提交的,咱們是否能夠在 Phase1 就將本地事務提交呢?這樣 90% 以上的狀況下,能夠省去 Phase2 持鎖的時間,總體提升效率。
這個設計,在絕大多數場景減小了事務持鎖時間,從而提升了事務的併發度。
固然,你確定會問:Phase1 即提交的狀況下,Phase2 如何回滾呢?
3.3 分支事務如何提交和回滾?
首先,應用須要使用 Fescar 的 JDBC 數據源代理,也就是 Fescar 的 RM。
Phase1:
Fescar 的 JDBC 數據源代理經過對業務 SQL 的解析,把業務數據在更新先後的數據鏡像組織成回滾日誌,利用本地事務 的 ACID 特性,將業務數據的更新和回滾日誌的寫入在同一個 本地事務中提交。
這樣,能夠保證:任何提交的業務數據的更新必定有相應的回滾日誌存在。
基於這樣的機制,分支的本地事務即可以在全局事務的 Phase1 提交,立刻釋放本地事務鎖定的資源。
Phase2:
若是決議是全局提交,此時分支事務此時已經完成提交,不須要同步協調處理(只須要異步清理回滾日誌),Phase2 能夠很是快速地完成。
若是決議是全局回滾,RM 收到協調器發來的回滾請求,經過 XID 和 Branch ID 找到相應的回滾日誌記錄,經過回滾記錄生成反向的更新 SQL 並執行,以完成分支的回滾。
3.4 事務傳播機制
XID 是一個全局事務的惟一標識,事務傳播機制要作的就是把 XID 在服務調用鏈路中傳遞下去,並綁定到服務的事務上下文中,這樣,服務鏈路中的數據庫更新操做,就都會向該 XID 表明的全局事務註冊分支,歸入同一個全局事務的管轄。
基於這個機制,Fescar 是能夠支持任何微服務 RPC 框架的。只要在特定框架中找到能夠透明傳播 XID 的機制便可,好比,Dubbo 的 Filter + RpcContext。
對應到 Java EE 規範和 Spring 定義的事務傳播屬性,Fescar 的支持以下:
3.5 隔離性
全局事務的隔離性是創建在分支事務的本地隔離級別基礎之上的。
在數據庫本地隔離級別讀已提交或以上的前提下,Fescar 設計了由事務協調器維護的 全局寫排他鎖,來保證事務間的寫隔離,將全局事務默認定義在讀未提交的隔離級別上。
咱們對隔離級別的共識是:絕大部分應用在 讀已提交 的隔離級別下工做是沒有問題的。而實際上,這當中又有絕大多數的應用場景,實際上工做在讀未提交的隔離級別下一樣沒有問題。
在極端場景下,應用若是須要達到全局的 讀已提交,Fescar 也提供了相應的機制來達到目的。默認,Fescar 是工做在 讀無提交 的隔離級別下,保證絕大多數場景的高效性。
事務的 ACID 屬性在 Fescar 中的體現是一個比較複雜的話題,咱們會有專門的文章來深刻分析,這裏不作進一步展開。
前文所述的 Fescar 的核心原理中有一個重要前提:分支事務中涉及的資源,必須是支持ACID 事務的 關係型數據庫。分支的提交和回滾機制,都依賴於本地事務的保障。因此,若是應用使用的數據庫是不支持事務的,或根本不是關係型數據庫,就不適用。
另外,目前 Fescar 的實現還存在一些侷限,好比:事務隔離級別最高支持到讀已提交的水平,SQL 的解析還不能涵蓋所有的語法等。
爲了覆蓋 Fescar 原生機制暫時不能支持應用場景,咱們定義了另一種工做模式。
上面介紹的 Fescar 原生工做模式稱爲 AT(Automatic Transaction)模式,這種模式是對業務無侵入的。與之相應的另一種工做模式稱爲 MT(Manual Transaction)模式,這種模式下,分支事務須要應用本身來定義業務自己及提交和回滾的邏輯。
4.1 分支的基本行爲模式
做爲全局事務一部分的分支事務,除自己的業務邏輯外,都包含 4 個與協調器交互的行爲:
4.2 AT 模式分支的行爲模式
業務邏輯不須要關注事務機制,分支與全局事務的交互過程自動進行。
4.3 MT 模式分支的行爲模式
業務邏輯須要被分解爲 Prepare/Commit/Rollback 3 部分,造成一個 MT 分支,加入全局事務。
MT 模式一方面是 AT 模式的補充。另外,更重要的價值在於,經過 MT 模式能夠把衆多非事務性資源歸入全局事務的管理中。
4.4 混合模式
由於 AT 和 MT 模式的分支從根本上行爲模式是一致的,因此能夠徹底兼容,即,一個全局事務中,能夠同時存在 AT 和 MT 的分支。這樣就能夠達到全面覆蓋業務場景的目的:AT 模式能夠支持的,使用 AT 模式;AT 模式暫時支持不了的,用 MT 模式來替代。另外,天然的,MT 模式管理的非事務性資源也能夠和支持事務的關係型數據庫資源一塊兒,歸入同一個分佈式事務的管理中。
4.5 應用場景的遠景
回到咱們設計的初衷:一個理想的分佈式事務解決方案是不該該侵入業務的。MT 模式是在 AT 模式暫時不能徹底覆蓋全部場景的狀況下,一個比較天然的補充方案。咱們但願經過 AT 模式的不斷演進加強,逐步擴大所支持的場景,MT 模式逐步收斂。將來,咱們會歸入對 XA 的原生支持,用 XA 這種無侵入的方式來覆蓋 AT 模式沒法觸達的場景。
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 存儲的方案。
藍圖
綠色部分是已經開源發佈出來的,黃色 部分是將在後續版本中由阿里發佈出來的,藍色部分是咱們和社區共建生態部分:
初步的版本規劃
v0.1.0:
v0.5.x:
v0.8.x:
v1.0.0:
v1.5.x:
v2.0.0:
固然,項目迭代演進的過程,咱們最重視的是社區的聲音,路線圖會和社區充分交流及時進行調整。
分享
本人13年Java開發經驗及產品研發經驗,BAT背景,曾在多家知名企業擔任技術總監、企業方案選型首席顧問,前後從事內核開發、大型Java系統架構設計和物聯網系統架構設計開發,精通複雜業務技術方案選型、架構、核心難點攻關,對於java語言及項目有很是深刻的理解和豐富的實操經驗,熱愛前沿技術,樂於進行技術分享與技術探討。