注:本文轉自https://yq.aliyun.com/articles/600584
本文介紹了螞蟻金服在分布式事務上,經過多年發展,服務于內外部大量不同業務,沉淀出的一整套包含TCC、FMT、XA模型的分布式事務解決方案。并且在持續對外輸出的過程中,進一步打磨產品體驗,適應各種嚴苛的金融級場景和機構需求,比如跨機房跨地域的容災業務連續性保障能力等。
隨著互聯網技術快速發展,數據規模增大,采用分布式數據庫或者跨多個數據庫的分布式微服務應用在中大規模企業普遍存在,而由于網絡、機器等不可靠因素,數據一致性的問題很容易出現,與可擴展性、高可用容災等要求并肩成為金融IT架構支撐業務轉型升級的最大挑戰之一。
在螞蟻金服核心系統提出微服務化時,曾遇到了非常大的技術難題。首先是在服務拆分以后,面臨跨服務的一致性問題;其次,支付寶當時的峰值交易量已經非常高了,在解決一致性問題的同時,還需要兼顧性能。
在當時,業界常用的分布式事務解決方案,通常能夠實現跨服務一致性,但在熱點數據的處理上,難以滿足性能需求。
因此,螞蟻金服微服務化過程中急需一種即能保證一致性,又能保證高性能的方案。當時經過一系列調研和討論,最終選擇了以BASE最終一致性思想為基礎,在業務層實現兩階段提交的TCC分布式事務解決方案,該方案既能保證跨服務的最終一致,又能通過業務靈活加鎖的方式大幅減少資源層加鎖時間,高效處理熱點問題。
隨著螞蟻金服業務不斷豐富,業務邏輯越來越復雜,同時螞蟻金融云上客戶也越來越多,對分布式事務解決方案(簡稱DTX,Distributed Transaction-eXtended)也不只是追求極限性能,也對接入便捷性、實時一致性有了要求。這篇文章將基于分布式事務在支付寶/螞蟻金服核心金融場景下的演進路線,分享介紹其在各階段的關鍵設計考量和發展思路。
一. 分布式事務在螞蟻金服的應用背景
1.1 支付寶 SOA 架構演進
最初的支付寶系統架構非常簡單,是一個典型的 Web 系統,交易、支付、賬務系統是沒有分開的,全部集中在一個大工程里,底層用DB 存儲,Web服務使用Spring等框架開發,最上層使用LB轉發用戶流量。
隨著代碼規模和業務邏輯復雜度的增長,將所有的業務模塊放在一個 Web服務內的缺點日益凸顯。因此推動了服務模塊化拆分,演進成SOA架構,很好地解決了應用的伸縮性問題。
在這個架構中,交易系統、支付系統、賬務系統分別獨立出來了,它們之間的調用靠RPC,除了服務模塊化拆分,還有數據庫的垂直拆分,根據業務系統功能,將數據庫拆分為多個,每個系統使用獨立的數據庫。
1.2 數據一致性問題
數據垂直拆分后,減少了單庫的性能瓶頸,但也帶來了數據一致性的問題。如下圖所示:
一筆轉賬業務需要跨交易、支付、賬務三個系統才能完成整個流程,并且要求這三個系統要么一起成功,要么一起失敗。如果有的成功,有的失敗,就有可能造成數據不一致,那么這個業務行為肯定不會被用戶所理解。所以,我們系統面臨的問題就是 SOA 架構下的數據一致性。
二. 關鍵設計考量:金融級一致性要求與海量并發處理能力
考慮到在解決一致性問題的同時,還要兼顧海量并發處理能力,螞蟻金服內部結合BASE 理論的思想,選擇在業務層實現2PC(兩階段事務提交)的方式來解決該問題。
BASE 理論是指 BA(Basic Availability,基本業務可用性);S(Soft state,柔性狀態);E(Eventual consistency,最終一致性)。該理論認為為了可用性、性能與降級服務的需要,可以適當降低一點一致性的要求,即“基本可用,最終一致”。
一般來講,在傳統的單機數據庫或者集中式存儲數據庫里,對于一致性的要求是實時一致;而對于分布式系統,服務與服務之間已經實現了功能的劃分,邏輯的解耦,也就更容易弱化一致性,允許處理過程中,數據的短暫不一致,只需要保證數據最終達到一致。
2.1 分布式金融核心的零差錯容忍保證:TCC模型
如本文開篇所述,螞蟻金服大部分系統的分布式事務解決方案以BASE最終一致性思想為基礎,在業務層實現兩階段提交的TCC(Try-Confirm-Cancel)分布式事務解決方案,以確保在一致性問題的保障和性能方面達到最佳平衡。
TCC 分布式事務模型包括三部分,如下所示
主業務服務:主業務服務為整個業務活動的發起方,服務的編排者,負責發起并完成整個業務活動。
從業務服務:從業務服務是整個業務活動的參與方,負責提供 TCC 業務操作供主業務服務調用
初步操作 Try:完成所有業務檢查,預留必須的業務資源。
確認操作 Confirm:真正執行的業務邏輯,不作任何業務檢查,只使用 Try 階段預留的業務資源。因此,只要 Try 操作成功,Confirm 必須能成功。另外,Confirm 操作需滿足冪等性,保證一筆分布式事務有且只能成功一次。
取消操作 Cancel:釋放 Try 階段預留的業務資源。同樣的,Cancel 操作也需要滿足冪等性。
業務活動管理器:業務活動管理器管理控制整個業務活動,包括記錄維護 TCC全局事務的事務狀態和每個從業務服務的子事務狀態,并在業務活動提交時調用所有從業務服務的Confirm 操作,在業務活動取消時調用所有從業務服務的Cancel 操作。
2.1.1 TCC 與 XA 對比 --- 并發性優勢
TCC把兩階段拆分成了兩個獨立的階段,通過資源業務鎖定的方式進行關聯。資源業務鎖定方式的好處在于,既不會阻塞其他事務在第一階段對于相同資源的繼續使用,也不會影響本事務第二階段的正確執行。
XA 模型的并發事務
TCC 模型的并發事務
從上面的對比可以發現,TCC模型相比 XA 模型進一步減少了資源鎖的持有時間。XA 模型下,在 Prepare 階段是不會把事務1所持有的鎖資源釋放掉的,如果事務2和事務1爭搶同一個資源,事務2必須等事務1結束之后才能使用該資源。
而在TCC里,因為事務1在Try階段已經提交了,那么事務2可以獲得互斥資源,不必再等待事務1的Confirm或Cancel階段執行完。也就是說,事務2的Try階段可以和事務1的Confirm或Cancel階段并行執行,從而獲得了一個比較大的并發性能提升。
2.2 保證大規模交易下的并發性能:極致性能優化
2010年開始,每年天貓雙十一大促的峰值交易量成倍增加,如下圖所示:
折線上的點代表著每一年的交易峰值(TPS)。前面講過,每次分布式事務需要協調多個參與方,因此,每年交易峰值乘以一個倍數才是分布式事務框架要協調最終達到一致性狀態的峰值分支事務數量。事實上,對分布式事務服務來說,2017年已經達到每秒百萬級水平。
回顧歷年大促,2013年對支付寶的交易處理是對我們挑戰很大的一年,2013年雙11提出的峰值目標,按照當時大促準備的計算和存儲資源,是無法完成的,怎么辦?
只能選擇繼續優化事務框架,讓它盡量少消耗資源,并去獲得一個更大的性能提升。我們根據 TCC 模型的特點以及日常開發時積累的經驗,針對性能問題,做了以下兩類優化。
2.2.1 極致性能優化之同庫模式
之前的業務活動管理器是一個單獨的服務,每次啟動業務活動、登記業務操作、提交或回滾業務活動等操作都需要與業務活動管理器交互,并且交互次數與參與者個數成正相關。
因此,為了追求極限性能,將業務活動管理器的遠程存儲替換成本地存儲,如下所示:
減少了RPC的調用,同時還會做一些減少存儲次數的優化,從而獲得性能收益。
通過這種方式,減少RPC調用耗時,大幅降低事務執行時間。同時還針對支付、賬務等訪問頻繁的特殊從業務服務,優化處理過程,不再創建單獨的分支事務記錄,而是將這個信息與主事務記錄合并,在創建主事務記錄的同時,記錄分支事務,最大程度減少與數據庫的交互次數,從而獲得更高的性能收益。
下面是同庫模式優化前后的時序圖對比:
優化前時序圖
優化后時序圖
其中,綠色方塊表示本地數據庫訪問??梢园l現,優化后減少了:(2+n) 次 PRC 延遲 + 1次數據庫訪問延遲(n表示參與者個數)。
2.2.2 極致性能優化之異步化
從理論上來說,只要業務允許,事務的第二階段什么時候執行都可以,因此資源已經被業務鎖定,不會有其他事務動用該事務鎖定的資源。如下圖所示:
這就是 TCC 分布式事務模型的二階段異步化功能,各從業務服務的第一階段執行成功以后,主業務服務就可以提交完成,框架會保證正確記錄事務狀態,然后再由框架異步的執行各從業務服務的第二階段,從而比較完整的詮釋最終一致性。
大促的尖峰時刻是從零點開始的幾十秒或一分鐘之內,在這個時刻的交易,我們會把二階段的操作從同步轉成異步,在沖高的那一刻,二階段就停止了,一階段正常扣款,等著交易零點三十分或者夜里一點開始回落的時候,我們才開始打開二階段,集中做二階段的動作。
優化后,Confirm 階段在空閑時段異步執行:
假設 Confirm 階段與 Try 階段耗時相同,單個事務耗時減少50%
數據庫資源消耗減少50%
三. 關鍵設計考量:無侵入自動化的接入體驗
眾所周知,螞蟻金服在近幾年除了支付業務以外,還發展出了很多復雜的金融業務,比如財富、保險、銀行等。同時,在2014年螞蟻金服全面開啟了金融云時代,也會對外賦能合作方和客戶。在這些新的場景下面,分布式事務產品面臨新的挑戰,客戶的性能需求可能不像螞蟻金服內部要求那么高,而是更關注接入的便利性和通用性,要求簡單易用,對業務代碼無侵入。因此,分布式事務產品開始全面升級,滿足更多客戶對云端產品的需求。
3.1 框架托管FMT(Framework-managed transactions)模型
TCC 模型作用于業務層,負責協調從業務服務的最終一致性。所有被納入到分布式事務的從業務服務,需要為框架提供Try、Confirm、Cancel三個方法,并且需要滿足冪等性。由于方法實現和要滿足的約束條件都需要業務方提供,這無疑就大大提高了接入門檻。所以我們在TCC 模型上繼續往前推進發展,提出了FMT 模型來解決接入便捷性的問題。
FMT 分布式事務模型與 TCC 模型類似,也同樣包含主業務服務、從業務服務、業務活動管理器,如下所示:
不同的是,從業務服務不再需要提供 Try、Confirm、Cancel三個方法,而是直接按照 JDBC 標準,通過托管框架與底層數據庫交互,就像使用普通數據源一樣。托管框架對業務來說是透明的,主要負責解析SQL語義,自動生成兩階段操作。
3.2 FMT 模型實現原理
托管框架的兩階段操作如下圖所示:
FMT 框架要求從業務服務只需要正常執行SQL操作就可以了,框架會把業務的本地事務操作作為第一階段。在第一階段,框架會攔截用戶SQL,解析SQL語義,然后把業務SQL涉及數據執行前后的狀態保存下來,即數據快照,這個就相當于在邏輯上完成了數據庫內的undo和redo操作。在第二階段,如果這個事務要提交,那么框架直接把快照數據刪除就可以了,因為第一階段的正常操作已經執行完成。如果該事務要回滾,那么會先校驗臟寫,根據第一階段保存的執行后的快照,檢查在本事務執行過程中,數據有沒有被其他操作修改,如果沒有,則把數據執行前的快照拿出來,完成回滾操作。
3.3 一階段示例
舉個例子,上圖左邊這張表有兩列,一列是賬號,另一列是金額。這時如果要針對該賬戶執行一條update操作,框架會怎么做呢?
在update之前,會先把賬戶的金額保存下來,執行update操作,然后把執行之后的金額保存下來。因為在二階段有可能會是回滾操作,回滾的時候如果想把執行之前的數據覆蓋回去的話,必須要保證在覆蓋的那個時刻,這些行上面的數據沒有被別人變更過,所以最后會加一個邏輯行鎖,這個就是金融系統的特性需求。
3.4 與數據訪問代理集成
為了更加簡化云上用戶接入,我們繼續和內部產品數據訪問代理DBP合作集成,如下所示:
分布式事務產品框架可以認為是被集成在數據訪問代理里,當進行一個事務時,上層業務方對于底下的分布式事務和本地事務是一視同仁的,通過數據代理看一個事務,并執行SQL。如果是分布式事務,數據訪問代理會通知框架去執行前面提到的一系列保證事務的操作,以保證數據的最終一致。
四. 關鍵設計考量:數據實時一致性、通用性、性能
4.1 XA模型
TCC和FMT兩個模型都是在最佳實踐上追求數據的最終一致性,而不是實時一致性。
我們分析了金融云上的客戶發現,如果把業務模型假定成數據最終一致性,那么依然有很多金融客戶不得不做出很大的妥協和變更,尤其是原有的業務組織模型和業務邏輯實現。而且這種妥協和調整的工作量是很大的,門檻也是非常高的。
所以我們基于標準XA做了一個XA模型來滿足客戶對數據實時一致性的需求。
原生XA協議提出至今,大概有10-20的時間了,但是在工業界應用的歷史和案子都很少。為什么會這樣呢?我們認為最重要的一點就是在追求數據實時一致性的同時,性能損失太大了。主要有兩個比較方面的性能損失,一個是讀和寫之間的沖突,另一個是寫與寫之間的沖突。
4.2 標準XA問題分析
了解數據庫內核的人都清楚,數據庫內部解決寫和非加鎖讀的沖突是通過MVCC機制來實現的。假如說最新的數據塊在更新的同時,你的讀是可以讀正在更新的數據塊的上一個快照。但是在分布式架構下,單機 MVCC 機制并不能滿足數據實時性一致性要求。
依然是轉賬業務場景,A 賬戶給 B 賬務轉賬10塊錢。但是 A 賬戶和 B賬戶分別在兩個數據庫分片 DB1 和 DB2 上。其操作執行過程如下所以:
如上圖所示,DB1 的本地子事務已經提交完畢,但是 DB2 的本地子事務還沒提交,這個時候只能讀到 DB1 上子事務執行的內容,讀不到 DB2 上的子事務。也就是說,雖然在單個 DB 上的本地事務是實時一致的,但是從全局來看,一個全局事務執行過程的中間狀態被觀察到了,全局實時一致性就被破壞了。
但是原生的 XA 協議沒有規定快照讀這個概念,也就沒有定義怎么實現全局實時一致性。最簡單的做法就是使用串行化的隔離級別,即使是快照讀也需要轉換為加鎖讀,從而來保證分布式事務的實時一致性。
當然,由于串行化隔離級別的性能較差,很多分布式數據庫都自己實現了分布式MVCC 機制來提供全局的實時一致性讀。一個基本思路是用一個集中式或者邏輯上單調遞增的東西來控制生成全局快照(Snapshot),每個事務或者每條 SQL 執行時都去獲取一次,從而實現不同隔離級別下的全局一致性,如下圖所示:
在 DB1 的本地子事務已經提交完畢,DB2 的本地子事務還沒提交的中間狀態,其他并發事務只能看到該事務執行之前的快照。
我們的分布式事務產品同樣實現了分布式 MVCC 機制,從而在保證實時一致性的同時,最大程度的保證讀寫并發性能。
4.3 并發寫優化 --- 與 OB 深度定制commit 延遲優化
除了實現分布式 MVCC 保證并發讀寫性能外,我們還與自研數據庫 OceanBase 深度定制優化并發寫,進一步提升產品性能,共同打造實時數據一致性的整體解決方案。
傳統標準的二階段提交過程如下:
其中,綠色方塊表示持久化日志,黃色方塊表示事務提交。從圖中可以看到,單次Commit 操作需要有3次日志延遲、1次事務延遲以及2次 RPC 延遲。
OceanBase 內部實現XA協議的時候,會在和協調者交互的時候附帶一些信息,并且在Commit時落盤,減少Commit過程中涉及到的RPC和落盤的操作,以達到減少用戶Commit時間的效果。
優化后時序圖如下:
雖然在 Commit操作之后,還有 Clear 操作,但是在執行 Clear 時,用戶的Commit請求已經返回了,所以并不影響用戶感知的 Commit 請求延遲。因此,從用戶感知的角度來說,單次 Commit 操作實際上只需要 1次日志延遲、1次事務延遲 以及 2次RPC延遲。
通過以上優化,兩階段提交與普通提交的落盤次數和RPC次數是相同的,也就是說耗時和普通提交相差無幾,寫和寫之間的沖突所帶來的額外性能消耗將被降低很大一部分。
五. 總結
總結關于分布式事務服務的關鍵設計考量,首先為了保障支付業務的核心需求,保障分布式環境下交易一致性的問題,我們基于BASE思想,在業務層實現了TCC 模型,并且為了業務發展的需求,優化了其工程實踐,實現海量并發處理能力,讓它的性能可以達到比業界其它產品高很多的狀態。
其次,因為上層業務系統的復雜、業務種類的豐富等等業務需求,對分布式事務解決方案提出了全新的要求,所以我們在TCC模型基礎上又加入了框架托管(FMT)模型,其簡單易用,對業務無侵入的特點,可以較好的解決金融云場景下接入便捷性問題。
最后,我們對數據實時一致性、通用性、性能再思考,與自研數據庫 OceanBase 深度定制,推出XA模型,共同打造實時數據一致性的整體分布式事務解決方案。
六. 了解更多:金融級云原生架構解決方案SOFA
通過十多年的探索與實踐,我們積累了大量的架構設計原則、最佳實踐和產品服務案例,并構建了一整套金融級云原生架構解決方案,這套架構叫做SOFA(Scalable Open Financial Architecture,分布式事務DTX亦是其重要的組成部分),源自螞蟻內部分布式架構實踐,是一整套完整的金融級中間件產品技術和演進式架構轉型服務體系,已經向國內金融機構開放,提供了完整的金融IT基礎架構轉型量身打造的技術平臺和可落地路徑,使業務應用能專注需求作敏捷交付,又能同時原生地擁有金融級的高可用、一致性特性和互聯網的海量并發、彈性伸縮等云原生基礎架構能力。