在去年的時候我寫過一篇關於分佈式事務的文章再有人問你分佈式事務,把這篇扔給他。再這篇文章中我叫你們能不用分佈式事務就別用分佈式事務,由於會引入不少的複雜度。當時說這個的時候其實還有一個緣由,沒有大廠的成熟開源解決方案,雖然再網上有不少開源的分佈式事務框架,可是都不是太成熟,沒有大量的業務驗證。它不像其餘的分佈式中間件有大量的成熟的解決方案,好比分佈式消息隊列中間件:Apache Kafka,Apache RocketMQ,Apache Pulsar這三個均是Apache頂級項目;又好比分佈式任務調度,也有不少的開源好比XXL-JOB,Elastic-Job都是有不少的公司在使用。java
而咱們的分佈式事務框架,卻一直沒有一個通過大量業務驗證的框架。經過個人一些瞭解,其實各大公司都是有本身的分佈式事務的解決方案,但不少時候都和業務上強耦合了,不適於作一些通用的框架。可是阿里在今年年初的時候給了你們一個驚喜,Fescar開源!從而讓你們再之後選擇分佈式事務的時候多了一個選擇方案,並且是通過成熟業務驗證的方案。git
這篇文章我會帶你們認識Fescar,以及他的一些設計。後續的文章還會陸續推出Fescar的核心源碼解析篇。github
說Fescar以前這裏先簡單的介紹一下著名的2PC:XA Transactions。 在XA協議中分爲兩階段: redis
第二階段:事務協調器要求每一個數據庫提交數據,或者回滾數據。數據庫
優勢: 儘可能保證了數據的強一致,實現成本較低,在各大主流數據庫都有本身實現,對於MySQL是從5.5開始支持。緩存
缺點:網絡
總的來講,XA協議比較簡單,成本較低,可是其單點問題,以及不能支持高併發(因爲同步阻塞)依然是其最大的弱點。併發
能夠看見XA協議問題較多因此其做爲分佈式事務方案討論的時候基本都會被無情的幹掉,可是XA有個很好優勢是對業務沒有侵入(數據庫層面),再業務上不須要編寫額外的代碼,更加關注業務。框架
在個人那篇文章中我又介紹了幾種在應用層面上的分佈式事務,可是或多或少的對業務都有必定的入侵。好比咱們的TCC,經常使用的一些TCC框架都須要編寫try,confirm,cancel等接口對於現成的業務須要進行轉換。若是採用本地消息表模式那麼又須要增長額外的表。若是採用事務性消息好比RocketMQ,會讓一些沒有使用該消息隊列的業務須要更換消息隊列。若是採用Saga模式,一樣咱們須要編寫正向和反向接口。能夠看見不論採用哪一種分佈式事務方案,都會有必定的業務改造,業務入侵成本。異步
而Fescar結合了XA的無侵入的優勢和其餘應用層事務協議高性能的優勢,在應用層實現了二階段協議的事務,同時對業務代碼基本無侵入。
Fescar雖然是二階段提交協議的分佈式事務,可是其解決了上面XA的一些缺點:
同時Fescar也保留了接近0業務入侵的優勢,只須要簡單的配置Fescar的數據代理和加個註解,加一個Undolog表,就能夠達到咱們想要的目的。
Fescar的設計核心就是他的角色分類。不管是數據庫上的XA仍是Fescar都有兩個角色TM(事務管理器)和RM(資源管理器),同時Fescar還有一個TC(事務協調器)。咱們先來看看若是沒有TC,只有TM和RM會發生什麼呢?這裏我舉個簡單的例子,小明去網站上面購買了一個商品,以下圖所示:
這裏小明其實就是TM(事務管理器),而商品和帳戶其實就是咱們的RM(資源管理器),正常狀況下可能沒問什麼問題,帳戶和庫存都能扣減成功。若是小明再扣減庫存的時候成功可是在扣減帳戶的時候失敗,這個時候就須要對咱們的庫存資源進行回滾。小明這個時候就會通知庫存把上個階段扣減的貨物補回來。可是回滾庫存的時候庫存服務不穩定,此次回滾就失敗了。通常來講小明會不斷的去重試,直到成功。這樣就有個問題小明就一直被阻塞,不能作任何事。這個也能夠看作二階段commit/rollback的時候一直會阻塞TM,網易DDB的XA協議針對這種狀況會作一個異步線程的操做。可是在Fescar中一切都是由TC去作的,固然TC其實不只僅會作二階段失敗的重試,他會作二階段的全部RM的commit和rollback,讓咱們的TM作更少的事。
再Fescar中TM,RM,TC的關係以下面官方提供的圖:
這三個角色的分工明確,正是咱們Fescar真正的核心所在,下面我會經過如何使用Fescar帶你們更加深入的理解這三個角色。
在Fescar的github上已經提供了一個簡單的例子https://github.com/fescar-group/fescar-samples,這裏咱們須要將這個例子下載下來。
首先咱們搭建事務協調器,也能夠叫作搭建Fescar-Server.官網的例子是使用Nacos加上fescar-server已經打好的Jar包運行的。這裏爲了方便咱們直接下載fescar的代碼https://github.com/alibaba/fescar。
找到咱們的Server:
直接運行main方法,該方法會幫助咱們在本地啓動一個端口號爲8091的fescar-server服務。若是咱們想要進行服務註冊,咱們能夠修改registry.conf下面的type
能夠看見在0.4.1版本的時候支持四種服務註冊,nacos,eureka,redis,zk。目前使用redis進行服務註冊是有問題的,我也提了一個PR給官方進行修正。固然爲了方便其實選擇file,後續咱們直連是最爲便捷的。
再運行main方法以後,若是出現Server started日誌,就表明咱們的TC(事務協調器)成功啓動。
上面事務協調器已經搭建完成,咱們接下來須要作的就是將TM和RM運行起來,將對應的操做交給咱們的事務協調器去作。這個時候咱們須要打開fescar-samples這個項目:因爲這個項目使用的RPC是Dubbo,他默認配的服務註冊中心是Nacos,須要咱們再本地安裝一個Nacos,具體安裝能夠自行搜索,這裏不展開講了。
這裏官方例子中,業務關係以下圖:
能夠看見Business也就是咱們的TM,找到對應的代碼:
從代碼中咱們知道啓動一個分佈式事務是須要添加@GlobalTransactional註解的,固然Fescar也提供了API的方式讓咱們達到一樣的效果。咱們同時也須要修改registry.conf中的Type爲file。
若是不是在例子中,而是在咱們真正的業務上徹底不須要修改業務代碼,直接在咱們分佈式事務發起方添加上這個註解便可。
這個GloablTranscational註解到底作了什麼呢?其實加了這個註解的都會走一個叫GlobalTransactionalInterceptor的切面,再這個切面中又會進入TrascationTemplate這個類中的excute方法,這個也是TM的核心方法:
上面的代碼有部分刪減,只選取了核心的流程。TrascationTemplate其實也是Fescar提供給咱們的API,若是不使用註解那麼咱們也能夠模仿他的方式去作。能夠看見主要分爲五步:
TM的核心過程主要是這5步,其餘詳細的講解會在後續的代碼中體現。
當咱們上面的Business發起業務請求以後,就來到了咱們RM的流程,咱們的Storage和Order服務是怎麼知道如今已是處於分佈式事務當中了呢?這個就須要藉助RPC框架來完成了,這裏咱們使用的是Dubbo,fescar爲dubbo提供了一個filter,以下圖所示:
這裏會從rpcContext中獲取咱們的xid,也就是咱們的分佈式事務ID,若是有的話就證實本次請求處於分佈式事務中,那麼就會把XID種入咱們的RootContext(fescar的本地上下文)。若是你不是Dubbo,那麼也能夠根據此方法適配你的RPC。
在RM中咱們應該作什麼呢?只須要作下面兩步:
再Fescar中不只僅是對dataSource進行代理,也會對connection和statement進行代理,以下圖:
你們都知道咱們的SQL的具體執行須要依賴Statement,在Fescar的StatementProxy中有以下代碼:
能夠看見運行的方法是ExecuteTemplate.execute,在execute方法中會根據咱們執行語句的類型記錄咱們的Undolog,具體的執行流程參考下面官方的一張圖片:
總的來講咱們的RM核心流程主要有兩個:一個是如何識別分佈式事務,另一個是經過咱們數據源代理讓咱們本來簡單的執行SQL流程作了更多的事。
寫這篇文章的目的,不只僅是讓你們知道Fescar,也是讓更多的人知道一個優秀分佈式事務框架到底應該怎樣去作。目前Fescar的版本號是0.4.1,還有不少功能好比HA-Cluster,SpringCloud集成尚未發佈。因此目前再線上使用的話可能會遇到Fescar單點的問題,因此目前還不是太推薦線上使用。Fescar的目前規劃會在0.5.x版本推出HA-Cluster,到時候其單點問題就會被解決。
這篇文章的原理目前介紹的比較粗淺,後面會陸續推出三篇文章詳細介紹分析:TC,TM,RM,敬請期待。
最後這篇文章被我收錄於JGrowing-Java分佈式事務篇,一個全面,優秀,由社區一塊兒共建的Java學習路線,若是您想參與開源項目的維護,能夠一塊兒共建,github地址爲:github.com/javagrowing… 麻煩給個小星星喲。
若是你們以爲這篇文章對你有幫助,你的關注和轉發是對我最大的支持,O(∩_∩)O:
阿里開源分佈式事務解決方案Fescar: mp.weixin.qq.com/s/TFGRcHV6E…