- 分佈式事務場景如何設計系統架構及解決數據一致性問題,我的理解最終方案把握如下原則就能夠了,那就是:大事務=小事務(原子事務)+異步(消息通知),解決分佈式事務的最好辦法其實就是不考慮分佈式事務,將一個大的業務進行拆分,整個大的業務流程,轉化成若干個小的業務流程,而後經過設計補償流程從而考慮最終一致性。
事務是由一組SQL語句組成的邏輯處理單元,事務具備如下4個屬性,一般簡稱爲事務的ACID屬性:html
原子性(Atomicity):事務是一個原子操做單元,其對數據的修改,要麼全都執行,要麼全都不執行。java
一致性(Consistent):在事務開始和完成時,數據都必須保持一致狀態。這意味着全部相關的數據規則都必須應用於事務的修改,以保持數據的完整性;事務結束時,全部的內部數據結構(如B樹索引或雙向鏈表)也都必須是正確的。算法
隔離性(Isoation):數據庫系統提供必定的隔離機制,保證事務在不受外部併發操做影響的「獨立」環境執行。這意味着事務處理過程當中的中間狀態對外部是不可見的,反之亦然。數據庫
持久性(Durabe):事務完成以後,它對於數據的修改是永久性的,即便出現系統故障也可以保持。編程
事務由資源管理器(如DBMS)本地管理跨域
優勢:嚴格的ACID
缺點:不具有分佈事務處理能力安全
TX協議:應用或應用服務器與事務管理器的接口服務器
XA協議:全局事務管理器與資源管理器的接口微信
本地事務和分佈式事務如今已經很是成熟,相關介紹很豐富,此處很少做討論。見《DTP模型之一:(XA協議之一)XA協議、二階段2PC、三階段3PC提交》網絡
基於組件的應用編程模型,經過申明式事務管理進一步簡化事務應用的編程
OASIS組織經過的Web Service事務標誌,包含WS-Cordination、WS-AtomicTransaction、WS-BusinessActivity
開源的JTA、JTS、WS-Transaction標準的實現
分佈式系統中就某個提議達成一致性的算法族
3.一、CAP(帽子戲法)
3.二、ACID-BASE Balance(酸鹼平衡)
服務模式之一:可查詢操做
複合模式1:按期校對
保證消息在事務提交後才發送
服務模式2:冪等操做
複合模式2:可靠消息
可靠消息的另外一種實現
服務模式3:TCC模式
服務模式4:可補償操做
複合模式4:補償模式
典型場景:銀行轉帳業務
例如:李雷帳戶中有500塊錢,韓梅梅帳戶有200塊錢,李雷要從本身的帳戶中轉100塊錢給韓梅梅,轉帳(事務)成功執行完成後應該是李雷帳戶減100變爲400,韓梅梅帳戶加100變爲300,不能出現其餘狀況,即在事務開始和結束時數據都必須保持一致狀態(一致性),事務結束時全部的數據及結構都必須是正確的。而且一樣的轉帳操做(同一流水,即一次轉帳操做)不管執行多少次結果都相同(冪等性)。
電商場景:流量充值業務
再說咱們作的一個項目:中國移動-流量充值能力中心,核心業務流程爲:
用戶進入流量充值商品購買頁面,選擇流量商品;
購買流量充值商品,有庫存限制則判斷庫存,生成流量購買訂單;
選擇對應的支付方式(和包、銀聯、支付寶、微信)進行支付操做;
支付成功後,近實時流量到帳便可使用流量商品;
此業務流程看似不是很複雜對吧,不涉及到相似電商業務的實物購買,可是我認爲其中的區別並非很大,只是缺乏電商中的物流發貨流程,其餘流程幾乎是同樣的,也有庫存以及優惠折扣等業務存在。
整個系統交互以下圖:
流量中心繫統交互圖流量中心繫統交互圖
分佈式事務
上述兩個場景的業務需求已經說完了,接着談談分佈式事務,要說分佈式事務那就先聊聊本地事務與分佈式事務:
Ps:相同點:首先都是要保證數據正確(即ACID),本地事務與分佈式事務還能夠對應爲:剛性事務與柔性事務,在我我的理解剛性事務與柔性事務的最大區別就是:一個完整的事務操做是否能夠在同一物理介質(例如:內存)上同時完成;柔性事務就是一個完整事務須要跨物理介質或跨物理節點(網絡通信),那麼排它鎖、共享鎖等等就沒有用武之地了(這裏並非指大事務拆小事務【本地事務】後),沒法保證原子性(Atomicity)完成事務。我的理解分佈式(柔性)事務本質意義上就是-僞事務,柔性事務其實就是根據不一樣的業務場景使用不一樣的方法實現最終一致性,由於能夠根據業務的特性作部分取捨,在業務過程當中能夠容忍必定時間內的數據不一致。
在知乎上面看過一篇文章,支付寶的柔性事務實現方式有四種分別針對不一樣的業務場景,以下圖:
柔性事務-轉自知乎做者:梁川柔性事務-轉自知乎做者:梁川
兩階段型
補償型
異步確保型
最大努力通知型
兩階段型
上面有介紹
補償型
如上面的TCC
異步確保型
經過將一系列同步的事務操做變爲基於消息執行的異步操做, 避免了分佈式事務中的同步阻塞操做的影響.這個方案真正實現了兩個服務的解耦, 解耦的關鍵就是異步消息和補償性事務。因爲消息可能會重複投遞,這 就要求消息處理程序必須實現冪等(冪等=同一操做反覆執行屢次結果不變),這一要求跟傳統應用開發相比是很是具備互聯網特徵的一種模式。
冪等
每種業務場景不一樣,實現冪等的方法也會有所不一樣,最簡單的冪等實現方式是根據業務流水號寫日誌,這種日誌也叫作排重表。
實現無鎖
數據庫性能和吞吐率瓶頸每每是由於強事務帶來的資源鎖。如何很好地解決數據庫鎖問題時實現高性能的關鍵所在。因此選擇放棄鎖是一個解決問題的思路,可是放棄鎖並不意味着放棄隔離性,若是隔離性沒有保障,則必然帶來大量的數據髒讀、幻讀等問題,最終致使業務不可控地不一致。
實現事務隔離的方法有不少,在實際的業務場景中可靈活選擇如下幾種典型的實現方式。
避免事務進入回滾。若是事務出現異常時,能夠不回滾也能知足業務的要求,也就是要求業務無論出現任何狀況,只能繼續朝事務處理流程的順向繼續處理,這樣中間狀態即便對外可見,因爲事務不會回滾,也不會致使髒讀。
輔助業務變化明細表。好比對資金或商品庫存進行增減處理時,可採用記錄這些增減變化的明細表的方式,避免全部事務均對同一數據表進行更新操做,形成數據訪問熱點,同時使得不一樣事務中處理的數據互不干擾,實現對資金或庫存信息處理的隔離。
樂觀鎖。數據庫的悲觀鎖對數據訪問具備極強的排他性,也是產生數據庫處理瓶頸的重要緣由,採用樂觀鎖則在必定程度上解決了這個問題。樂觀鎖大可能是基於數據版本記錄機制實現。
這裏以一個例子做爲講解:
執行步驟以下:
須要額外說明的一點, 就是事務消息投遞到MQ訂閱方後, 並不必定可以成功執行. 須要MQ訂閱方主動給予消費反饋(ack)
例如:
這是分佈式事務中要求最低的一種, 也能夠經過消息中間件實現, 與前面異步確保型操做不一樣的一點是, 在消息由MQ Server投遞到消費者以後, 容許在達到最大重試次數以後正常結束事務.
交易結果消息的通知等.