注冊用戶即可下載全站資源 關注Java幫幫微信公眾號
 

柔性事務 :TCC兩階段補償型

9
發表時間:2018-12-11 15:30

   TCC方案是可能是目前最火的一種柔性事務方案了。關于TCC(Try-Confirm-Cancel)的概念,最早是由Pat Helland于2007年發表的一篇名為《Life beyond Distributed Transactions:an Apostate’s Opinion》的論文提出。在該論文中,TCC還是以Tentative-Confirmation-Cancellation命名。正式以Try-Confirm-Cancel作為名稱的是Atomikos公司,其注冊了TCC商標。

   國內最早關于TCC的報道,應該是InfoQ上對阿里程立博士的一篇采訪。經過程博士的這一次傳道之后,TCC在國內逐漸被大家廣為了解并接受。

日本韩国三级aⅴ在线观看    Atomikos公司在商業版本事務管理器ExtremeTransactions中提供了TCC方案的實現,但是由于其是收費的,因此相應的很多的開源實現方案也就涌現出來,如:tcc-transaction、ByteTCC、spring-cloud-rest-tcc。

日本韩国三级aⅴ在线观看   TCC的作用主要是解決跨服務調用場景下的分布式事務問題,在本文中,筆者將先介紹一個跨服務的場景案例,并分析其中存在的分布式事務問題;然后介紹TCC的基本概念以及其是如何解決這個問題的。

場景案例

日本韩国三级aⅴ在线观看    Atomikos官網上<<Composite Transactions for SOA>>一文中,以航班預定的案例,來介紹TCC要解決的事務場景。在這里筆者虛構一個完全相同的場景,把自己當做航班預定的主人公,來介紹這個案例。事實上,你可以把本案例當做官方文檔案例的一個翻譯,只不過把地點從Brussels-->Toronto-->Washington,改成從合肥-->昆明-->大理。

日本韩国三级aⅴ在线观看    有一次,筆者買彩票中獎了(純屬虛構),準備從合肥出發,到云南大理去游玩,然后使用美團App(機票代理商)來訂機票。發現沒有從合肥直達大理的航班,需要到昆明進行中轉。如下圖:

B121F546-2D0F-45F5-962D-758B07337692.png

   從圖中我們可以看出來,從合肥到昆明乘坐的是四川航空,從昆明到大理乘坐的是東方航空。

日本韩国三级aⅴ在线观看    由于使用的是美團App預定,當我選擇了這種航班預定方案后,美團App要去四川航空和東方航空各幫我購買一張票。如下圖:

B87CD059-6891-4A30-A5C4-B8EC7735EADF.png

   考慮最簡單的情況:美團先去川航幫我買票,如果買不到,那么東航也沒必要買了。如果川航購買成功,再去東航購買另一張票。

日本韩国三级aⅴ在线观看    現在問題來了:假設美團先從川航成功買到了票,然后去東航買票的時候,因為天氣問題,東航航班被取消了。那么此時,美團必須取消川航的票,因為只有一張票是沒用的,不取消就是浪費我的錢。那么如果取消會怎樣呢?如果讀者有取消機票經歷的話,非正常退票,肯定要扣手續費的。在這里,川航本來已經購買成功,現在因為東航的原因要退川航的票,川航應該是要扣代理商的錢的。

   那么美團就要保證,如果任一航班購買失敗,都不能扣錢,怎么做呢?

日本韩国三级aⅴ在线观看    兩個航空公司都為美團提供以下3個接口:機票預留接口、確認接口、取消接口。美團App分2個階段進行調用,如下所示:

F58C00A0-976A-4295-818C-C9F96B191060.png

在第1階段:

   美團分別請求兩個航空公司預留機票,兩個航空公司分別告訴美圖預留成功還是失敗。航空公司需要保證,機票預留成功的話,之后一定能購買到。

在第2階段:

   如果兩個航空公司都預留成功,則分別向兩個公司發送確認購買請求。

   如果兩個航空公司任意一個預留失敗,則對于預留成功的航空公司也要取消預留。這種情況下,對于之前預留成功機票的航班取消,也不會扣用戶的錢,因為購買并沒實際發生,之前只是請求預留機票而已。

日本韩国三级aⅴ在线观看    通過這種方案,可以保證兩個航空公司購買機票的一致性,要不都成功,要不都失敗,即使失敗也不會扣用戶的錢。如果在兩個航班都已經已經確認購買后,再退票,那肯定還是要扣錢的。

日本韩国三级aⅴ在线观看    當然,實際情況肯定這里提到的肯定要復雜,通常航空公司在第一階段,對于預留的機票,會要求在指定的時間必須確認購買(支付成功),如果沒有及時確認購買,會自動取消。假設川航要求10分鐘內支付成功,東航要求30分鐘內支付成功。以較短的時間算,如果用戶在10分鐘內支付成功的話,那么美團會向兩個航空公司都發送確認購買的請求,如果超過10分鐘(以較短的時間為準),那么就不能進行支付。

   再次強調,這個案例,可以算是<<Composite Transactions for SOA>>中航班預定案例的漢化版。而實際美團App是如何實現這種需要中轉的航班預定需求,筆者并不知情。

   另外,注意這只是一個案例場景,實際情況中,你是很難去驅動航空公司進行接口改造的。

   Whatever,這個方案提供給我們一種跨服務條用保證事務一致性的一種解決思路,可以把這種方案當做TCC的雛形。

TCC 的基本概念

TCC是Try-Confirm-Cancel的簡稱:

Try階段:

日本韩国三级aⅴ在线观看    完成所有業務檢查(一致性),預留業務資源(準隔離性)

日本韩国三级aⅴ在线观看    回顧上面航班預定案例的階段1,機票就是業務資源,所有的資源提供者(航空公司)預留都成功,try階段才算陳宮

Confirm階段:

   確認執行業務操作,不做任何業務檢查, 只使用Try階段預留的業務資源。回顧上面航班預定案例的階段2,美團APP確認兩個航空公司機票都預留成功,因此向兩個航空公司分別發送確認購買的請求。

Cancel階段:

   取消Try階段預留的業務資源。回顧上面航班預定案例的階段2,如果某個業務方的業務資源沒有預留成功,則取消所有業務資源預留請求。


敏銳的讀者立馬會想到,TCC與XA兩階段提交有著異曲同工之妙,下圖列出了二者之間的對比:

D7087D1B-1E4D-4C0E-8BA4-B2A8B36D0132.png

日本韩国三级aⅴ在线观看  1) 在階段1:

   在XA中,各個RM準備提交各自的事務分支,事實上就是準備提交資源的更新操作(insert、delete、update等);而在TCC中,是主業務活動請求(try)各個從業務服務預留資源。

 2) 在階段2:

日本韩国三级aⅴ在线观看    XA根據第一階段每個RM是否都prepare成功,判斷是要提交還是回滾。如果都prepare成功,那么就commit每個事務分支,反之則rollback每個事務分支。

   TCC中,如果在第一階段所有業務資源都預留成功,那么confirm各個從業務服務,否則取消(cancel)所有從業務服務的資源預留請求。


TCC兩階段提交與XA兩階段提交的區別是:

   XA是資源層面的分布式事務,強一致性,在兩階段提交的整個過程中,一直會持有資源的鎖。

      XA事務中的兩階段提交內部過程是對開發者屏蔽的,回顧我們之前講解JTA規范時,通過UserTransaction的commit方法來提交全局事務,這只是一次方法調用,其內部會委派給TransactionManager進行真正的兩階段提交,因此開發者從代碼層面是感知不到這個過程的。而事務管理器在兩階段提交過程中,從prepare到commit/rollback過程中,資源實際上一直都是被加鎖的。如果有其他人需要更新這兩條記錄,那么就必須等待鎖釋放。

  TCC是業務層面的分布式事務,最終一致性,不會一直持有資源的鎖。

    TCC中的兩階段提交并沒有對開發者完全屏蔽,也就是說從代碼層面,開發者是可以感受到兩階段提交的存在。如上述航班預定案例:在第一階段,航空公司需要提供try接口(機票資源預留)。在第二階段,航空公司提需要提供confirm/cancel接口(確認購買機票/取消預留)。開發者明顯的感知到了兩階段提交過程的存在。try、confirm/cancel在執行過程中,一般都會開啟各自的本地事務,來保證方法內部業務邏輯的ACID特性。其中:

日本韩国三级aⅴ在线观看    1、try過程的本地事務,是保證資源預留的業務邏輯的正確性。

   2、confirm/cancel執行的本地事務邏輯確認/取消預留資源,以保證最終一致性,也就是所謂的補償型事務(Compensation-Based Transactions)。

由于是多個獨立的本地事務,因此不會對資源一直加鎖。

另外,這里提到confirm/cancel執行的本地事務是補償性事務,關于什么事補償性事務,atomikos 官網上有以下描述:

C6467FCC-0325-4DA9-9B21-D263C19710D2.png

   紅色框中的內容,是對補償性事務的解釋。大致含義是,"補償是一個獨立的支持ACID特性的本地事務,用于在邏輯上取消服務提供者上一個ACID事務造成的影響,對于一個長事務(long-running transaction),與其實現一個巨大的分布式ACID事務,不如使用基于補償性的方案,把每一次服務調用當做一個較短的本地ACID事務來處理,執行完就立即提交”。

日本韩国三级aⅴ在线观看    在這里,筆者理解為confirm和cancel就是補償事務,用于取消try階段本地事務造成的影響。因為第一階段try只是預留資源,之后必須要明確的告訴服務提供者,這個資源你到底要不要,對應第二階段的confirm/cancel。

   提示:讀者現在應該明白為什么把TCC叫做兩階段補償性事務了,提交過程分為2個階段,第二階段的confirm/cancel執行的事務屬于補償事務。

TCC事務模型 VS DTP事務模型

日本韩国三级aⅴ在线观看在介紹完TCC的基本概念之后,我們再來比較一下TCC事務模型和DTP事務模型,如下所示:

C014B9B7-F334-4C95-BCEA-59A7897DA651.png

日本韩国三级aⅴ在线观看這兩張圖看起來差別較大,實際上很多地方是類似的!

1、TCC模型中的主業務服務 相當于 DTP模型中的AP,TCC模型中的從業務服務 相當于 DTP模型中的RM

日本韩国三级aⅴ在线观看      在DTP模型中,應用AP操作多個資源管理器RM上的資源;而在TCC模型中,是主業務服務操作多個從業務服務上的資源。例如航班預定案例中,美團App就是主業務服務,而川航和東航就是從業務服務,主業務服務需要使用從業務服務上的機票資源。不同的是DTP模型中的資源提供者是類似于Mysql這種關系型數據庫,而TCC模型中資源的提供者是其他業務服務。

2、TCC模型中,從業務服務提供的try、confirm、cancel接口 相當于 DTP模型中RM提供的prepare、commit、rollback接口

   XA協議中規定了DTP模型中定RM需要提供prepare、commit、rollback接口給TM調用,以實現兩階段提交。

日本韩国三级aⅴ在线观看    而在TCC模型中,從業務服務相當于RM,提供了類似的try、confirm、cancel接口。

3、事務管理器

    DTP模型和TCC模型中都有一個事務管理器。不同的是:

    在DTP模型中,階段1的(prepare)和階段2的(commit、rollback),都是由TM進行調用的。

日本韩国三级aⅴ在线观看     在TCC模型中,階段1的try接口是主業務服務調用(綠色箭頭),階段2的(confirm、cancel接口)是事務管理器TM調用(紅色箭頭)。這就是 TCC 分布式事務模型的二階段異步化功能,從業務服務的第一階段執行成功,主業務服務就可以提交完成,然后再由事務管理器框架異步的執行各從業務服務的第二階段。這里犧牲了一定的隔離性和一致性的,但是提高了長事務的可用性。問題來了,既然第二階段是異步執行的,主業務服務怎么知道異步執行的結果呢?發消息異步通知?返回一個id,后面讓業務去查?

TCC事務的優缺點:

   優點:XA兩階段提交資源層面的,而TCC實際上把資源層面二階段提交上提到了業務層面來實現。有效了的避免了XA兩階段提交占用資源鎖時間過長導致的性能地下問題。

   缺點:主業務服務和從業務服務都需要進行改造,從業務方改造成本更高。還是航班預定案例,原來只需要提供一個購買接口,現在需要改造成try、confirm、canel3個接口,開發成本高。


提示:國內有一些關于TCC方案介紹的文章中,把TCC分成三種類型:

  • 日本韩国三级aⅴ在线观看通用型TCC,如果我們上面介紹的TCC模型實例,從業務服務需要提供try、confirm、cancel

  • 日本韩国三级aⅴ在线观看補償性TCC,從業務服務只需要提供 Do 和 Compensate 兩個接口

  • 異步確保型 TCC,主業務服務的直接從業務服務是可靠消息服務,而真正的從業務服務則通過消息服務解耦,作為消息服務的消費端,異步地執行。

日本韩国三级aⅴ在线观看關于這種劃分,筆者并不贊同,基于兩點:

   1、筆者在Atomikos在官網上參考了多份資料,并沒有看到這種劃分,猜測應該是這些公司在內部實踐中,自行提出的概念。

日本韩国三级aⅴ在线观看    2、對于上面所謂的"補償性TCC”、”異步確保型 TCC”,從業務服務不需要提供try、confirm、cancel三個接口,在這種情況下,好像稱之為TCC也不太合適。

TCC For REST案例

日本韩国三级aⅴ在线观看    通過前面的介紹,我們基本已經掌握了TCC的工作原理。在本節中,筆者借用Atomikos官網提供的<<Tcc For Rest>>進行TCC案例講解。

   需要注意的是,這個案例的主要目的是說明,在使用基于HTTP的REST服務中,TCC模型中各個參與方的API接口應該如何設計。通常一個TCC方案是不會依賴于底層通信框架的,例如我們也可以使用業界比較火的spring cloud、dubbo等。這個時候,提供實現類似接口的功能就可以了。

首先我們總結一下TCC模型各個參與方需要提供的API:

  Participant API:日本韩国三级aⅴ在线观看從業務服務需要提供的API,其需要提供try接口供主業務服務調用,需要提供confirm、cancel接口供事務管理器調用。這里將從業務服務稱之為Participant。

   Transaction Coordinator API:事務管理/協調器需要提供的API,其需要提供事務日志上報接口,讓主業務活動上報try階段各個從業務活動資源是否預留成功的信息

   Application:日本韩国三级aⅴ在线观看主業務服務,其不需要提供任何接口,只需要操作上述 Participant、 Transaction Coordinator提供的接口即可。

   熟悉的配方,熟悉的味道,<<Tcc For Rest>>采用的依然航班預定案例,如下圖所示:

  72591582-FCFB-4109-A75C-D7269B157249.png

其中:

日本韩国三级aⅴ在线观看Booking Proccess是主業務活動,處理機票預定業務

Swiss和easyjet是從業務服務,可以理解為兩個不同航空公司的機票預定系統

日本韩国三级aⅴ在线观看Transaction Coordinator是事務協調器,或者稱之為事務管理器。

上圖中描述的整體流程如下所示:

日本韩国三级aⅴ在线观看1 Booking Proccess接受到一個需要中轉的航班預定請求(bookTrip)

   -1.1:Booking Proccess向swiss發起機票預定請求 R1,其中/booking/A表示swis提供的預留機票資源的try接口

日本韩国三级aⅴ在线观看    -1.2:Booking Proccess向easyjet發起機票預定請求 R2,其中/booking/B表示easyjet提供的預留機票資源的try接口

日本韩国三级aⅴ在线观看    -1.3:Booking Proccess將請求1.1、1.2步驟中try的結果合并上報給Transaction Coordinator。

         -1.3.1 Transaction Coordinator 向swiss發送確認執行業務操作的請求

日本韩国三级aⅴ在线观看          -1.3.2 Transaction Coordinator 向easyjet發送確認執行業務操作的請求

Participant API

   從業務服務需要提供try、confirm和cancel三個接口,其中try接口是給主業務服務調用的,confirm和cancel是給事務協調器調用的。

try接口

日本韩国三级aⅴ在线观看    在1.1和1.2步驟中,Booking Proccess向swiss和easyjet提供的try接口分別發起機票預留請求,swiss和easyjet作為參與者,返回的響應格式如下所示

  1. {"participantLink":

  2.    {"uri":"http://www.example.com/part/123",

  3.    "expires":"2014-01-11T10:15:54Z"

  4.    }

  5. }

這里返回的是一個JSON格式,事實上返回的格式什么是無所謂的,不過Atomikos官方建議使用JSON格式。其中:

   uri :表示的是稍后在Confirm確認執行業務操作時,需要調用的url

日本韩国三级aⅴ在线观看    expires:表示截止時間,也就是說,如果超過這個時間依然沒有確認購買,那么swiss和easyjet將會自動取消這個機票的預留

confirm接口

   Transaction Coordinator判斷資源都預留成功,解析出json格式中的uri部分,向swiss和easyjet發送確認執行請求(Confirm),請求格式如下:

  1. PUT /part/123 HTTP/1.1

  2. Host: www.example.com

  3. Accept: application/tcc

日本韩国三级aⅴ在线观看注意請求頭中Accept接受的MIME類型, 暗示了客戶端的語義期望。 這個并不是強制的。  

如果swiss和easyjet都確認執行成功,應該返回204,表示執行成功

  1. HTTP/1.1 204 No Content

   需要注意的是,如果在截止時間(expires)后發送確認執行的請求,swiss和easyjet應該返回404

  1. HTTP/1.1 404 Not Found

   而Transaction Coordinator自身也應該有這種超時判斷,以為較小的expires為準,當超過這個時間時,就不應該發送confirm確認執行的請求。

日本韩国三级aⅴ在线观看    而在expires之前如果確認執行失敗,Transaction Coordinator應該進行重試。


cancel接口(可選實現)

日本韩国三级aⅴ在线观看    參與者可以選擇是否顯式的提供cancel接口,如果提供了。Transaction Coordinator應該發送DELETE請求,告訴參與者取消資源預留,格式如下

  1. DELETE /part/123 HTTP/1.1

  2. Host: www.example.com

  3. Accept: application/tcc

日本韩国三级aⅴ在线观看    如果取消成功,則返回

  1. HTTP/1.1 204 No Content

   如果取消失敗,也不會影響結果。前面提到過,資源預留都有一個expires截止時間,超過這個截止時間,參與者就可以主動取消這個預留的資源。

日本韩国三级aⅴ在线观看    如果是因為超時,參與者自行取消資源預留的情況下,應該返回

  1. HTTP/1.1 404 Not Found

   另外,由于參與具備超時自動取消預留的功能,因此DELETE接口是可選的。如果參與者不提供DELETE接口來支持顯式cancel,可以返回

  1. HTTP/1.1 405 Method Not Allowed

      不過筆者還是建議顯式的提供cancel接口,例如,如果swiss預留成功,easyjet預留失敗。對于預留失敗的情況,其實我們已經沒有必要進行cancel了。但是swiss預留成功了,如果等待超時自動取消,可能會比較耗時,通過顯式提供cancel接口,來更快的取消預留的資源,將機票賣給其他客戶。

Transaction Coordinator API

   TCC模型中,主業務服務需要將事務日志上報給事務管理器/協調器,然后由協調器來調用從業務服務的confirm或者cancel接口。因此事務管理器/協調器必須提供一個事務日志上報的接口。而本節就是介紹這個接口接受的參數類型和響應類型。

   主業務服務在第一階段,調用各個從業務服務的try接口,并且將響應合并起來上傳報給Transaction Coordinator。考慮一下,這里應該分為2種情況:

日本韩国三级aⅴ在线观看1、所有的try接口都調用成功了,因此主業務服務希望Transaction Coordinator向各個從業務服務進行confirm

日本韩国三级aⅴ在线观看2、try接口部分成功,部分失敗。因此主業務服務希望Transaction Coordinator對已經try成功的從業務服務都進行cancel

   因此對Transaction Coordinator來說,需要提供2個事務日志上報接口:confirm接口、cancel接口.

confirm接口

請求格式如下:

  1. PUT /coordinator/confirm HTTP/1.1

  2. Host: www.taas.com

  3. Content-Type: application/tcc+json

  4. {

  5.  "participantLinks": [

  6.     {

  7.     "uri": "http://www.example.com/part1",

  8.     "expires": "2014-01-11T10:15:54Z"

  9.     },

  10.     {

  11.     "uri": "http://www.example.com/part2",

  12.     "expires": "2014-01-11T10:15:54+01:00"

  13.     }

  14.  ]

  15. }

日本韩国三级aⅴ在线观看然后協調器會對參與者逐個發起Confirm請求, 如果一切順利那么將會返回如下結果

  1. HTTP/1.1 204 No Content

如果發起Confirm請求的時間太晚, 那么意味著所有被動方都已經進行了超時補償

  1. HTTP/1.1 404 Not Found

最糟糕的情況就是有些參與者確認了, 但是有些就沒有. 這種情況就應該要返回409, 這種情況在Atomikos中定義為啟發式異常

  1. HTTP/1.1 409 Conflict

   當然, 這種情況應該盡量地避免發生, 要求Confirm與Cancel實現冪等性, 出現差錯時協調器可多次對參與者重試以盡量降低啟發性異常發生的幾率. 萬一409真的發生了, 則應該由請求方主動進行檢查或者由協調器返回給請求方詳細的執行信息, 例如對每個參與者發起故障診斷的GET請求, 記錄故障信息并進行人工干預.

cancel接口

一個cancel請求跟confirm請求類似, 都是使用PUT請求, 唯一的區別是URI的不同

唯一可預見的響應就是

  1. HTTP/1.1 204 No Content

日本韩国三级aⅴ在线观看因為當預留資源沒有被確認時最后都會被釋放, 所以參與者返回其他錯誤也不會影響最終一致性。


支付寶贊助-Java幫幫社區
微信贊助-Java幫幫社區
Java幫幫公眾號生態

Java幫幫公眾號生態

總有一款適合你

Java幫幫-微信公眾號

Java幫幫-微信公眾號

將分享做到極致

Python幫幫-公眾號

Python幫幫-公眾號

人工智能,爬蟲,學習教程

大數據驛站-微信公眾號

大數據驛站-微信公眾號

一起在數據中成長

九點編程-公眾號

九點編程-公眾號

深夜九點學編程

程序員生活志-公眾號

程序員生活志-公眾號

互聯網,職場,程序員那些事兒

Java幫幫學習群生態

Java幫幫學習群生態

總有一款能幫到你

Java學習群

Java學習群

與大牛一起交流

大數據學習群

大數據學習群

在數據中成長

九點編程學習群

九點編程學習群

深夜九點學編程

python學習群

python學習群

人工智能,爬蟲

測試學習群

測試學習群

感受測試的魅力

Java幫幫生態承諾

Java幫幫生態承諾

一直堅守,不負重望

初心
勤儉
誠信
正義
分享
合作品牌 非盈利生態-優質內容分享傳播者
關于我們
友鏈申請
友鏈交換:加幫主QQ2524138991 留言即可 24小時內答復  
全站內容非商業用途,內容來源于網友,并遵循 許可,如有異議請聯系客服。
會員登錄
獲取驗證碼
登錄
登錄
我的資料
留言
回到頂部