天天看點

微服務架構下分布式事務解決方案 —— 阿裡GTS

雖然微服務現在如火如荼,但對其實踐其實仍處于探索階段。很多中小型網際網路公司,鑒于經驗、技術實力等問題,微服務落地比較困難。如著名架構師Chris Richardson所言,目前存在的主要困難有如下幾方面:

1)單體應用拆分為分布式系統後,程序間的通訊機制和故障處理措施變的更加複雜。

2)系統微服務化後,一個看似簡單的功能,内部可能需要調用多個服務并操作多個資料庫實作,服務調用的分布式事務問題變的非常突出。

3)微服務數量衆多,其測試、部署、監控等都變的更加困難。

随着RPC架構的成熟,第一個問題已經逐漸得到解決。例如dubbo可以支援多種通訊協定,springcloud可以非常好的支援restful調用。對于第三個問題,随着docker、devops技術的發展以及各公有雲paas平台自動化運維工具的推出,微服務的測試、部署與運維會變得越來越容易。

交易中間件與資料庫通過 XA 接口規範,使用兩階段送出來完成一個全局事務, XA 規範的基礎是兩階段送出協定。

第一階段是表決階段,所有參與者都将本事務能否成功的資訊回報發給協調者;第二階段是執行階段,協調者根據所有參與者的回報,通知所有參與者,步調一緻地在所有分支上送出或者復原。

微服務架構下分布式事務解決方案 —— 阿裡GTS

兩階段送出方案應用非常廣泛,幾乎所有商業OLTP資料庫都支援XA協定。但是兩階段送出方案鎖定資源時間長,對性能影響很大,基本不适合解決微服務事務問題。

微服務架構下分布式事務解決方案 —— 阿裡GTS

事務開始時,業務應用會向事務協調器注冊啟動事務。之後業務應用會調用所有服務的try接口,完成一階段準備。之後事務協調器會根據try接口傳回情況,決定調用confirm接口或者cancel接口。如果接口調用失敗,會進行重試。

TCC方案讓應用自己定義資料庫操作的粒度,使得降低鎖沖突、提高吞吐量成為可能。 當然TCC方案也有不足之處,集中表現在以下兩個方面:

對應用的侵入性強。業務邏輯的每個分支都需要實作try、confirm、cancel三個操作,應用侵入性較強,改造成本高。

實作難度較大。需要按照網絡狀态、系統故障等不同的失敗原因實作不同的復原政策。為了滿足一緻性的要求,confirm和cancel接口必須實作幂等。

上述原因導緻TCC方案大多被研發實力較強、有迫切需求的大公司所采用。微服務倡導服務的輕量化、易部署,而TCC方案中很多事務的處理邏輯需要應用自己編碼實作,複雜且開發量大。

微服務架構下分布式事務解決方案 —— 阿裡GTS

消息方案從本質上講是将分布式事務轉換為兩個本地事務,然後依靠下遊業務的重試機制達到最終一緻性。基于消息的最終一緻性方案對應用侵入性也很高,應用需要進行大量業務改造,成本較高。

性能超強

GTS通過大量創新,解決了事務ACID特性與高性能、高可用、低侵入不可兼得的問題。單事務分支的平均響應時間在2ms左右,3台伺服器組成的叢集可以支撐3萬TPS以上的分布式事務請求。

應用侵入性極低

GTS對業務低侵入,業務代碼最少隻需要添加一行注解(@TxcTransaction)聲明事務即可。業務與事務分離,将微服務從事務中解放出來,微服務關注于業務本身,不再需要考慮反向接口、幂等、復原政策等複雜問題,極大降低了微服務開發的難度與工作量。

完整解決方案

GTS支援多種主流的服務架構,包括EDAS,Dubbo,Spring Cloud等。

有些情況下,應用需要調用第三方系統的接口,而第三方系統沒有接入GTS。此時需要用到GTS的MT模式。GTS的MT模式可以等價于TCC模式,使用者可以根據自身業務需求自定義每個事務階段的具體行為。MT模式提供了更多的靈活性,可能性,以達到特殊場景下的自定義優化及特殊功能的實作。

容錯能力強

GTS解決了XA事務協調器單點問題,實作真正的高可用,可以保證各種異常情況下的嚴格資料一緻。

GTS包括用戶端(GTS Client)、資料總管(GTS RM)和事務協調器(GTS Server)三個部分。GTS Client主要用來界定事務邊界,完成事務的發起與結束。GTS RM完成事務分支的建立、送出、復原等操作。GTS Server主要負責分布式事務的整體推進,事務生命周期的管理。GTS和微服務內建的結構圖如下所示,GTS Client需要和業務應用內建部署,RM與微服務內建部署。

微服務架構下分布式事務解決方案 —— 阿裡GTS

GTS目前有三種輸出形式:公有雲輸出、公網輸出、專有雲輸出。

這種輸出形式面向阿裡雲使用者。如果使用者的業務系統已經部署到阿裡雲上,可以申請開通公有雲GTS。開通後業務應用即可通過GTS保證服務調用的一緻性。這種使用場景下,業務系統和GTS間的網絡環境比較理想,達到很好性能。

微服務架構下分布式事務解決方案 —— 阿裡GTS

這種輸出形式面向于非阿裡雲的使用者,使用更加友善、靈活,業務系統隻要能連接配接網際網路即可享受GTS提供的雲服務(與公有雲輸出的差别在于用戶端部署于使用者本地,而不在雲上)。

在正常網絡環境下,以包含兩個本地事務的全局事務為例,事務完成時間在20ms左右,50個并發就可以輕松實作1000TPS以上分布式事務,對絕大多數業務來說性能是足夠的。在公網環境,網絡閃斷很難完全避免,這種情況下GTS仍能保證服務調用的資料一緻性。

微服務架構下分布式事務解決方案 —— 阿裡GTS

具體使用樣例使用參見4.7節GTS的工程樣例。

這種形式主要面向于已建設了自己專有雲平台的大使用者,GTS可以直接部署到使用者的專有雲上,為專有雲提供分布式事務服務。目前已經有10多個特大型企業的專有雲使用GTS解決分布式事務難題,性能與穩定性經過了使用者的嚴格檢測。

GTS對應用的侵入性非常低,使用也很簡單。下面以訂單存儲應用為例說明。訂單業務應用通過調用訂單服務和庫存服務完成訂單業務,服務開發架構為Dubbo。

在業務函數外圍使用@TxcTransaction注解即可開啟分布式事務。Dubbo應用通過隐藏參數将GTS的事務xid傳播到服務端。

<code></code>

<code>}</code>

更新庫存方法

GTS目前已經在淘寶、天貓、阿裡影業、淘票票、阿裡媽媽、1688等阿裡各業務系統廣泛使用,經受了16年和17年兩年雙十一海量請求的考驗。某線上業務系統最高流量已達十萬TPS(每秒鐘10萬筆事務)。

微服務架構下分布式事務解決方案 —— 阿裡GTS

上圖是GTS與SpringCloud內建,應用于某共享出行系統。業務共享出行場景下,通過GTS支撐物聯網系統、訂單系統、支付系統、運維系統、分析系統等系各統應用的資料一緻性,保證海量訂單和數千萬流水的交易。

該樣例是GTS的入門sample,案例的業務邏輯是從A賬戶轉賬給B賬戶,其中A和B分别位于兩個MySQL資料庫中,使用GTS事務保證A和B賬戶錢的總數始終不變。

1) 準備資料庫環境

安裝MySQL,建立兩個資料庫db1和db2。在db1和db2中分别建立txc_undo_log表(SQL腳本見4.7.3)。在db1庫中建立user_money_a表,在db2庫中建立user_money_b表。

2) 下載下傳樣例

将sample-txc-simple檔案下載下傳到本地,樣例中已經包含了GTS的SDK。

3) 修改配置

打開sample-txc-simple/src/main/resources目錄下的txc-client-context.xml,将資料源的url、username、password修改為實際值。

4) 運作樣例

在sample-txc-simple目錄下執行build.sh編譯本工程。編譯完成後執行run.sh。

本案例模拟了使用者下訂單、減庫存的業務邏輯。用戶端(Client)通過調用訂單服務(OrderService)建立訂單,之後通過調用庫存服務(StockService)扣庫存。其中訂單服務讀寫訂單資料庫,庫存服務讀寫庫存資料庫。由 GTS 保證跨服務事務的一緻性。

安裝MySQL,建立兩個資料庫db1和db2。在db1和db2中分别建立txc_undo_log表。在db1庫中建立orders表,在db2庫中建立stock表。

将樣例檔案sample-txc-dubbo下載下傳到本地機器,樣例中已經包含了GTS的SDK。

打開sample-txc-dubbo/src/main/resources目錄,将dubbo-order-service.xml、dubbo-stock-service.xml兩個檔案中資料源的url、username、password修改為實際值。

4) 運作樣例

編譯程式

在工程根目錄執行 build.sh 指令,編譯工程。編譯後會在 sample-txc-dubbo/client/bin 目錄下生成 order_run.sh、stock_run.sh、client_run.sh 三個運作腳本對應訂單服務、庫存服務以及用戶端。

運作程式

在根目錄執行run.sh,該腳本會依次啟動order_run.sh(訂單服務)、stock_run.sh(庫存服務)和client_run.sh(用戶端程式)。

樣例使用Multicast注冊中心的聲明方式。如果本機使用無線網絡,dubbo服務在綁定位址時有可能擷取ipv6位址,可以通過jvm啟動參數禁用。

方法是配置jvm啟動參數 -Djava.net.preferIPv4Stack=true。

CREATE TABLE <code>txc_undo_log</code> (

<code>id</code> bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵',

<code>gmt_create</code> datetime NOT NULL COMMENT '建立時間',

<code>gmt_modified</code> datetime NOT NULL COMMENT '修改時間',

<code>xid</code> varchar(100) NOT NULL COMMENT '全局事務ID',

<code>branch_id</code> bigint(20) NOT NULL COMMENT '分支事務ID',

<code>rollback_info</code> longblob NOT NULL COMMENT 'LOG',

<code>status</code> int(11) NOT NULL COMMENT '狀态',

<code>server</code> varchar(32) NOT NULL COMMENT '分支所在DB IP',

PRIMARY KEY (<code>id</code>),

KEY <code>unionkey</code> (<code>xid</code>,<code>branch_id</code>)

) ENGINE=InnoDB AUTO_INCREMENT=211225994 DEFAULT CHARSET=utf8 COMMENT='事務日志表';

CREATE TABLE <code>user_money_a</code> (

<code>id</code> int(11) NOT NULL AUTO_INCREMENT,

<code>money</code> int(11) DEFAULT NULL,

PRIMARY KEY (<code>id</code>)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE <code>user_money_b</code> (

CREATE TABLE <code>orders</code> (

<code>id</code> bigint(20) NOT NULL AUTO_INCREMENT,

<code>user_id</code> varchar(255) NOT NULL,

<code>product_id</code> int(11) NOT NULL,

<code>number</code> int(11) NOT NULL,

<code>gmt_create</code> timestamp NOT NULL,

) ENGINE=MyISAM AUTO_INCREMENT=351 DEFAULT CHARSET=utf8

CREATE TABLE <code>stock</code> (

<code>price</code> float NOT NULL,

<code>amount</code> int(11) NOT NULL,

PRIMARY KEY (<code>product_id</code>)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

GTS已經在阿裡内部廣泛使用,經過了雙十一流量高峰的考驗。内部成熟後,在專有雲和公有雲服務了很多使用者,很多使用者一天事務量在千萬/億級别,解決了業務服務化改造後的分布式事務棘手技術難題。

在整個世界範圍内,既滿足事務ACID特性,又具備高性能、高可用、業務侵入性低的分布式事務中間件在GTS前是不存在的。讓我們一起體驗GTS帶來的巨大變革吧!

想了解更多GTS資訊,可以參考以下内容:

<a href="https://www.aliyun.com/aliware/txc">GTS(TXC)官網</a>

<a href="https://weibo.com/jiangyu666">研發團隊微網誌</a>