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