再論分佈式事務:從理論到實踐

 

  在前面《從銀行轉帳失敗到分佈式事務:總結與思考》一文中,已經總結了分佈式事務的各類解決方法,以及本身的一點思考。本文算是對上文的一個補充:進一步的思考,主要是這些解決方法在工程上的具體實施。若是後面在工做學習中有新的想法,也會持續更新到本文。html

  本文地址:http://www.cnblogs.com/xybaby/p/7756163.html數據庫

  在前文中,已經簡要介紹了2PC、TCC、基於異步消息、1PC這幾種分佈式事務解決辦法,這裏在補充一種:best effort。segmentfault

Best Effort

  best effort即盡最大努力交付,主要用於在這樣一種場景:不一樣的服務平臺之間的事務性保證。好比咱們在電商購物,使用支付寶支付;又好比玩網遊的時候,經過App Store充值。拿購物爲例,電商平臺與支付平臺是相互獨立的,隸屬於不一樣的公司,即便是同一個公司也極可能是獨立的部門。所以,這兩個平臺是不可能使用同一套分佈式事務框架的,2PC不行,tcc也不行,異步消息也不行。安全

  其實在上面電商平臺與支付平臺的例子中,涉及到多重事務性:服務器

  電商平臺與支付平臺之間的事務性:電商的下單操做與支付平臺扣款的原子性,不能說支付平臺扣了用戶的錢,但電商平臺不發貨;或者說,電商平臺先發了貨,支付平臺沒有扣用戶的錢;網絡

  電商平臺內部的事務性:好比訂單與優惠券、紅包等;架構

  支付平臺內部的事務性:好比用戶帳戶、商戶帳戶等;併發

  不論是由於技術緣由,仍是說安全策略,支付平臺只會提供給電商平臺一些Http接口,即開放支付服務。電商平臺在發出一筆支付請求後,是不大可能馬上得到支付是成功仍是失敗的確切消息,更多的時候應該是請求已被接受,處理中。這個時候支付平臺已經將該請求持久化,保證必定會處理這個請求。當支付平臺處理完這個支付請求以後,怎麼將結果通知給電商平臺呢,要麼是電商平臺定時輪訓,要麼是電商平臺在初始支付請求的時候攜帶一個callback,提供給支付平臺回調。在這篇文章中提到,支付寶採用的是回調的形式:oracle

  「作過支付寶交易接口的同窗都知道,咱們通常會在支付寶的回調頁面和接口裏,解密參數,而後調用系統中更新交易狀態相關的服務,將訂單更新爲付款成功。同時,只有當咱們回調頁面中輸出了success字樣或者標識業務處理成功相應狀態碼時,支付寶纔會中止回調請求。不然,支付寶會每間隔一段時間後,再向客戶方發起回調請求,直到輸出成功標識爲止。」框架

  這個例子,繪製成流程圖就是這樣樣子的:

  

  再想一想上文提到的銀行轉帳的例子,極可能也是採用best effort這種模式,銀行之間確定是相互獨立的。首先是本地銀行先扣款,而後通知另一個銀行加款,但爲何對方加款失敗,沒有通知到本地銀行,就不清楚了

分佈式事務解決方案比較

  在這裏主要經過如下幾個維度來對比分析:

  • 一致性
  • 資源鎖粒度:是否要利用到數據庫的鎖機制,加鎖的粒度
  • 子事務串並行:組成 一個事務的多個子事務是併發執行,仍是串行執行
  • 回滾(補償):是哪一個層面的回滾(補償)、回滾的代價

  注意,上面提到的回滾和補償是一個意思,「回滾」不侷限於DB裏面的術語,而是指通用的對某個操做的逆反操做

 

  

 

  2PC的強一致性依賴於數據庫,而TCC的強一致性依賴於應用層的Commit與cancel。異步消息,1PC,best effort都只保證最終一致性(且最終一致性還可能依賴於人工介入,是否應該算弱一致性?)

   2PC須要對整個資源加鎖,所以不適用於高併發的分佈式場景;而tcc只對須要的資源進行加鎖,加鎖的粒度小,且try commit Cancel都是本地短事務,所以能在保證強一致性的同時最大化提升系統可用性。而異步消息,1PC,best effort都是先提交一部分事務,無需加鎖。

  2PC是有數據庫來保證回滾,而TCC是應用層實現回滾:爲每個try操做提供一個對應的cancel操做。而異步消息,1PC適用於理論上必定會成功的場景,難以回滾。best effort這種模式,須要服務的調用者實現完整的一個事務操做用於回滾,好比支付失敗的狀況。數據庫的回滾較簡單,而應用層的回滾較爲困難,更重要的是,回滾也須要做爲一個事務進行,部分回滾失敗的狀況最可怕。

  至於子事務的串行、並行,在其餘文章中並無看見過相關討論,但確定是實踐的時候必需要考慮的問題。即一個分佈式事務確定是由多個分支事務組成,那麼多個分支事務是併發執行,仍是串行執行呢?特別對於2PC,TCC這些分爲多個階段的解決方案,每一個階段是併發,仍是串行呢

分支事務串並行與LPO

   首先,對於異步消息,best effort,確定都是串行的,其中一個分支事務完成以後,再去作另外一個分支事務。

   但對於2PC,TCC,理論上看起來是並行的,但工程實踐中有能夠串行。以2PC爲例

  2PC從介紹的文章來看,多屬於並行:即協調者同時讓參與者prepare,而後在第二階段同時通知參與者commit或者abort,下面兩個圖說明了這個並行的過程。

   

  上面分別是兩階段提交協議成功commit與失敗abort的狀況,能夠看出在prepare階段,多個參與者是並行的。

 

  而2PC的串行模式,就是說,先通知一個參與者準備,成功的話再通知另外一個參與者準備,即準備階段是串行的。下圖來自支付寶

   

  注意 上面的圖示,第二階段(commit 或者 abort)也畫成串行的,這裏應該是能夠並行的。

  

  那麼串行、並行的區別在於哪裏呢

   (1)並行效率高,整個事務的耗時更少;

   (2)而串行在prepare階段失敗的狀況下,只需部分回滾;

   

  在工程實踐中爲何會採用串行這種方式呢,這是另一個重要的優化: 「最末參與者優化」(Last Participant Optimization,術語來自支付寶),即容許兩階段提交協議中有一個參與者不實現「準備」操做,在其他參與者都prepare ok的狀況下,直接提交本身的分式事務。

   網絡上關於LPO的介紹並很少,在oracle官網Logging Last Resource Transaction Optimization中有以下介紹:

 The LLR resource uses a local transaction for its transaction work. The WebLogic Server transaction manager prepares all other resources in the transaction and then determines the commit decision for the global transaction based on the outcome of the LLR resource’s local transaction.  

   最末參與者優化的原理以下圖所示:

   

  本質上,LPO是將最後一個參與者的準備操做與提交/放棄操做合併成一個提交操做,這樣提升了分佈式事務的執行效率。也能夠看到,要使用LPO,在prepare階段必定是串行的。

 

  對於TCC,流程也是很是相似2PC,即在Try階段,也可使用LPO,在說說分佈式事務 一文中,給出了一個實例的詳細流程圖。

  在一些業務場景,是無需單獨的協調者,即事務的發起者同時是組成事務的分支事務。好比支付寶的例子,業務服務和帳戶服務組成一個分佈式事務,在業務服務上發起事務請求,所以沒有單獨的協調者服務器,使用LPO也比較適合。

再論TCC

  前面已經介紹過TCC的三個階段,Try負責預留資源,Commit提交預留的資源,Cancel「回滾」預留的資源。那麼某一個分支事務的Try操做是否能夠直接作Commit所作的事情呢,即Try操做直接提交分支事務。在這種狀況下,若是全部分支事務的Try階段都返回OK,那麼該分支事務的Commit就什麼都不用作,若是須要Cancel,那麼就實現回滾。

  固然,我看到的更多形式,好比支付寶的XTS,都只是凍結資源:加額外的字段,代表有多少數量的資源處於特殊狀態。

  咱們以一個扣款操做做爲分支事務,好比要從帳戶A扣除100元。若是Try階段直接執行事務,那麼就從A的帳戶上真正扣除了,而Cancel階段則加上100,看起來很容易;若是Try階段只是凍結,那麼就會複雜一些,一個可行的方案增長forzen字段的值,同時扣除帳戶。

  但若是考慮加款操做做爲分支事務,Try階段直接執行事務的話,極可能出現cancel階段錢不夠的狀況(假設資金不能爲負)

  所以,我的以爲,TCC框架是不用關心具體形式的,業務只需向框架註冊這三個操做就好了,具體怎麼操做,徹底取決於業務,能知足業務的需求就行。

  

實踐案例

  在龍果學院退出的課程《微服務架構的分佈式事務解決方案》中,綜合運用了各類分佈式事務解決方案,以下如所示:

  

  在上圖中,使用了三種分佈式事務解決辦法:

  (1)基於可靠消息的最終一致性方案(異步確保型),這個使用比較廣,適用於分支事務大機率成功的狀況;

  上圖中使用於:對應支付系統會計異步記帳業務,銀行通知結果信息存儲與驅動訂單處理

  (2)TCC事務補償性方案,使用在同時須要保證一致性與高性能的場景

  對應上圖中支付系統的訂單帳戶操做:訂單處理,資金帳戶處理,積分帳戶處理

  (3)best effort,最大努力通知型方案,適用於跨平臺之間的事務原子性保證

  對應上圖中支付系統的商戶業務通知場景

 

references

從銀行轉帳失敗到分佈式事務:總結與思考

支付寶分佈式事務設計草案

說說分佈式事務 

微服務架構的分佈式事務解決方案 

相關文章
相關標籤/搜索