分佈式事務之一:總體介紹

  • 分佈式事務場景如何設計系統架構及解決數據一致性問題,我的理解最終方案把握如下原則就能夠了,那就是:大事務=小事務(原子事務)+異步(消息通知),解決分佈式事務的最好辦法其實就是不考慮分佈式事務,將一個大的業務進行拆分,整個大的業務流程,轉化成若干個小的業務流程,而後經過設計補償流程從而考慮最終一致性。

1、基本概念

原則

  • 真正重要的是知足業務需求,而不是追求抽象、絕對的系統特性
  • 帽子戲法
  • 酸鹼(ACID-BASE Balance)

模式

  • 服務模式
    • 可查詢操做
    • 冪等操做
    • TCC操做
    • 可補償操做
  • 複合模式
    • 按期校對
    • 可靠消息
    • TCC
    • 補償

一、事務(Transaction)及其ACID屬性

事務是由一組SQL語句組成的邏輯處理單元,事務具備如下4個屬性,一般簡稱爲事務的ACID屬性:html

  1. 原子性(Atomicity):事務是一個原子操做單元,其對數據的修改,要麼全都執行,要麼全都不執行。java

  2. 一致性(Consistent):在事務開始和完成時,數據都必須保持一致狀態。這意味着全部相關的數據規則都必須應用於事務的修改,以保持數據的完整性;事務結束時,全部的內部數據結構(如B樹索引或雙向鏈表)也都必須是正確的。算法

  3. 隔離性(Isoation):數據庫系統提供必定的隔離機制,保證事務在不受外部併發操做影響的「獨立」環境執行。這意味着事務處理過程當中的中間狀態對外部是不可見的,反之亦然。數據庫

  4. 持久性(Durabe):事務完成以後,它對於數據的修改是永久性的,即便出現系統故障也可以保持。編程

二、事務分本地事務和分佈式事務

2.一、本地事務

事務由資源管理器(如DBMS)本地管理跨域

優勢:嚴格的ACID
缺點:不具有分佈事務處理能力安全

2.二、全局事務(DTP模型)

TX協議:應用或應用服務器與事務管理器的接口服務器

XA協議:全局事務管理器與資源管理器的接口微信

  • 優勢:嚴格的ACID
  • 缺點:效率很是低

兩階段提交(2PC)

  • 優勢
    • 準備後,仍可提交或回滾
    • 準備時,一致性檢查必須OK
    • 準備後,事務結果仍然只在事務內可見
    • 準備後,事務結果已經持久化
  • 缺點:
    • 潛在故障點多帶來的脆弱性
    • 準備後,提交前的故障引起一系列隔離與恢復難題

本地事務和分佈式事務如今已經很是成熟,相關介紹很豐富,此處很少做討論。見《DTP模型之一:(XA協議之一)XA協議、二階段2PC、三階段3PC提交網絡

2.三、跨域的全局事務(DTP模型)

  • 缺點
    • 更高的協議成本
    • 脆弱,故障點多
    • 故障影響大,恢復困難
    • 複雜,更多架構與平臺約束

 

2.四、java企業平臺中的分佈式事務實現

  • JTA
    • 面向應用、應用服務器與資源管理器的高層事務接口
  • JTS
    • JTA事務管理器的實現標準,向上支持JTA,向下經過CORBA OTS實現跨事務域的互操做性
  • EJB

     基於組件的應用編程模型,經過申明式事務管理進一步簡化事務應用的編程

  • 優勢
    • 簡單一致的編程模型
    • 跨域分佈處理的ACID保證
  • 侷限
    • DTP模型自己的侷限
    • 缺乏充分公開的大規模、高可用、密集事務應用的成功案例

 

2.五、其它資源

  • ws-transaction標準

    OASIS組織經過的Web Service事務標誌,包含WS-Cordination、WS-AtomicTransaction、WS-BusinessActivity

  • jbossTransaction系統

    開源的JTA、JTS、WS-Transaction標準的實現

  • Paxos算法

    分佈式系統中就某個提議達成一致性的算法族

三、分佈式原則

3.一、CAP(帽子戲法)

 

3.二、ACID-BASE Balance酸鹼平衡

 

詳見《CAP原則(CAP定理)、BASE理論》 

四、模式

  • 服務模式
    • 可查詢操做
    • 冪等操做
    • TCC操做
    • 可補償操做
  • 複合模式
    • 按期校對
    • 可靠消息
    • TCC
    • 補償

服務模式之一:可查詢操做

 

 

 

 

複合模式1:按期校對

保證消息在事務提交後才發送

服務模式2:冪等操做

複合模式2:可靠消息

可靠消息的另外一種實現

服務模式3:TCC模式

 

 服務模式4:可補償操做

複合模式4:補償模式

 

典型場景:銀行轉帳業務

例如:李雷帳戶中有500塊錢,韓梅梅帳戶有200塊錢,李雷要從本身的帳戶中轉100塊錢給韓梅梅,轉帳(事務)成功執行完成後應該是李雷帳戶減100變爲400,韓梅梅帳戶加100變爲300,不能出現其餘狀況,即在事務開始和結束時數據都必須保持一致狀態(一致性),事務結束時全部的數據及結構都必須是正確的。而且一樣的轉帳操做(同一流水,即一次轉帳操做)不管執行多少次結果都相同(冪等性)。

電商場景:流量充值業務

再說咱們作的一個項目:中國移動-流量充值能力中心,核心業務流程爲:

  1. 用戶進入流量充值商品購買頁面,選擇流量商品;

  2. 購買流量充值商品,有庫存限制則判斷庫存,生成流量購買訂單;

  3. 選擇對應的支付方式(和包、銀聯、支付寶、微信)進行支付操做;

  4. 支付成功後,近實時流量到帳便可使用流量商品;

此業務流程看似不是很複雜對吧,不涉及到相似電商業務的實物購買,可是我認爲其中的區別並非很大,只是缺乏電商中的物流發貨流程,其餘流程幾乎是同樣的,也有庫存以及優惠折扣等業務存在。

整個系統交互以下圖:

流量中心繫統交互圖流量中心繫統交互圖

 

分佈式事務

上述兩個場景的業務需求已經說完了,接着談談分佈式事務,要說分佈式事務那就先聊聊本地事務與分佈式事務:

Ps:相同點:首先都是要保證數據正確(即ACID),本地事務與分佈式事務還能夠對應爲:剛性事務與柔性事務,在我我的理解剛性事務與柔性事務的最大區別就是:一個完整的事務操做是否能夠在同一物理介質(例如:內存)上同時完成;柔性事務就是一個完整事務須要跨物理介質或跨物理節點(網絡通信),那麼排它鎖、共享鎖等等就沒有用武之地了(這裏並非指大事務拆小事務【本地事務】後),沒法保證原子性(Atomicity)完成事務。我的理解分佈式(柔性)事務本質意義上就是-僞事務,柔性事務其實就是根據不一樣的業務場景使用不一樣的方法實現最終一致性,由於能夠根據業務的特性作部分取捨,在業務過程當中能夠容忍必定時間內的數據不一致。

在知乎上面看過一篇文章,支付寶的柔性事務實現方式有四種分別針對不一樣的業務場景,以下圖:

 

柔性事務-轉自知乎做者:梁川柔性事務-轉自知乎做者:梁川

  1. 兩階段型 

  2. 補償型

  3. 異步確保型

  4. 最大努力通知型

  5. 引入日誌和補償機制:相似傳統數據庫,柔性事務的原子性主要由日誌保證。事務日誌記錄事務的開始、結束狀態,可能還包括事務參與者信息。參與者節點也須要根據重作或回滾需求記錄REDO/UNDO日誌。當事務重試、回滾時,能夠根據這些日誌最終將數據恢復到一致狀態。爲了不單點,事務日誌記錄在分佈式節點上的,一般柔性事務能經過日誌記錄找回事務的當前執行狀態,並根據狀態決定是重試異常步驟(正向補償),仍是回滾前序步驟(反向補償)。
  6. 可靠消息傳遞:

兩階段型 

  上面有介紹

補償型

  如上面的TCC 

異步確保型

  經過將一系列同步的事務操做變爲基於消息執行的異步操做, 避免了分佈式事務中的同步阻塞操做的影響.這個方案真正實現了兩個服務的解耦, 解耦的關鍵就是異步消息和補償性事務。因爲消息可能會重複投遞,這 就要求消息處理程序必須實現冪等(冪等=同一操做反覆執行屢次結果不變),這一要求跟傳統應用開發相比是很是具備互聯網特徵的一種模式。

冪等

每種業務場景不一樣,實現冪等的方法也會有所不一樣,最簡單的冪等實現方式是根據業務流水號寫日誌,這種日誌也叫作排重表。

實現無鎖

數據庫性能和吞吐率瓶頸每每是由於強事務帶來的資源鎖。如何很好地解決數據庫鎖問題時實現高性能的關鍵所在。因此選擇放棄鎖是一個解決問題的思路,可是放棄鎖並不意味着放棄隔離性,若是隔離性沒有保障,則必然帶來大量的數據髒讀、幻讀等問題,最終致使業務不可控地不一致。

實現事務隔離的方法有不少,在實際的業務場景中可靈活選擇如下幾種典型的實現方式。

避免事務進入回滾。若是事務出現異常時,能夠不回滾也能知足業務的要求,也就是要求業務無論出現任何狀況,只能繼續朝事務處理流程的順向繼續處理,這樣中間狀態即便對外可見,因爲事務不會回滾,也不會致使髒讀。

輔助業務變化明細表。好比對資金或商品庫存進行增減處理時,可採用記錄這些增減變化的明細表的方式,避免全部事務均對同一數據表進行更新操做,形成數據訪問熱點,同時使得不一樣事務中處理的數據互不干擾,實現對資金或庫存信息處理的隔離。

樂觀鎖。數據庫的悲觀鎖對數據訪問具備極強的排他性,也是產生數據庫處理瓶頸的重要緣由,採用樂觀鎖則在必定程度上解決了這個問題。樂觀鎖大可能是基於數據版本記錄機制實現。

 

 

這裏以一個例子做爲講解:

執行步驟以下:

  1. MQ發送方發送遠程事務消息到MQ Server;
  2. MQ Server給予響應, 代表事務消息已成功到達MQ Server.
  3. MQ發送方Commit本地事務.
  4. 若本地事務Commit成功, 則通知MQ Server容許對應事務消息被消費; 若本地事務失敗, 則通知MQ Server對應事務消息應被丟棄.
  5. 若MQ發送方超時未對MQ Server做出本地事務執行狀態的反饋, 那麼須要MQ Servfer向MQ發送方主動回查事務狀態, 以決定事務消息是否能被消費.
  6. 當得知本地事務執行成功時, MQ Server容許MQ訂閱方消費本條事務消息.

須要額外說明的一點, 就是事務消息投遞到MQ訂閱方後, 並不必定可以成功執行. 須要MQ訂閱方主動給予消費反饋(ack)

  • 若是MQ訂閱方執行遠程事務成功, 則給予消費成功的ack, 那麼MQ Server能夠安全將事務消息移除;
  • 若是執行失敗, MQ Server須要對消息從新投遞, 直至消費成功.

注意事項

  • 消息中間件在系統中扮演一個重要的角色, 全部的事務消息都須要經過它來傳達, 因此消息中間件也須要支持 HAC 來確保事務消息不丟失.
  • 根據業務邏輯的具體實現不一樣,還可能須要對消息中間件增長消息不重複, 不亂序等其它要求.

適用場景

  • 執行週期較長
  • 實時性要求不高

例如:

  • 跨行轉帳/匯款業務(兩個服務分別在不一樣的銀行中)
  • 退貨/退款業務
  • 財務, 帳單統計業務(先發送到消息中間件, 而後進行批量記帳)

最大努力通知型

這是分佈式事務中要求最低的一種, 也能夠經過消息中間件實現, 與前面異步確保型操做不一樣的一點是, 在消息由MQ Server投遞到消費者以後, 容許在達到最大重試次數以後正常結束事務.

適用場景

交易結果消息的通知等.

參考

相關文章
相關標籤/搜索