微服务--分布式事务的实现方法及替代方案
這兩天正在研究微服務架構中分布式事務的處理方案, 做一個小小的總結, 作為備忘. 如有錯誤, 歡迎指正!
概念澄清
事務補償機制: 在事務鏈中的任何一個正向操作, 都必須存在一個完全符合回滾規(guī)則的可逆操作, 這個操作通常叫做rollback或者cancel.
CAP理論: CAP(Consistency, Availability, Partition Tolerance), 闡述了一個分布式系統(tǒng)的三個主要方面, 只能同時擇其二進行實現(xiàn). 常見的有CP系統(tǒng), AP系統(tǒng).
為什么CA不行呢? 因為沒有P的話, 數(shù)據(jù)一致性會出現(xiàn)問題, 這是任何一個一致性系統(tǒng)不允許出現(xiàn)的情況.
冪等性: 簡單的說, 業(yè)務操作支持重試, 不會產(chǎn)生不利影響. 常見的實現(xiàn)方式: 為消息額外增加唯一ID.
BASE(Basically avaliable, soft state, eventually consistent): 是分布式事務實現(xiàn)的一種理論標準.
柔性事務 vs. 剛性事務
剛性事務是指強一致性事務, 例如單機環(huán)境下遵循ACID的數(shù)據(jù)庫事務, 或者分布式環(huán)境中的2PC等.
柔性事務是指遵循BASE理論的事務, 通常用在分布式環(huán)境中, 常見的實現(xiàn)方式有: 異步確保型, 最大努力通知型.
最佳實踐
先上結論, 再分別介紹分布式事務的各種實現(xiàn)方式.
如果業(yè)務場景需要強一致性, 那么盡量避免將它們放在不同服務中, 也就是盡量使用本地事務, 避免使用強一致性的分布式事務(例如2PC).
如果業(yè)務場景能夠接受最終一致性, 那么最好是使用異步確保型來解決(實際上大部分互聯(lián)網(wǎng)公司的業(yè)務都是這么玩兒的).
注意: 以下每種方案都有不同的適用場合, 需要根據(jù)實際業(yè)務場景來選擇.
兩階段提交(2PC)
兩階段提交(Two Phase Commit, 2PC), 具有強一致性, 是CP系統(tǒng)的一種典型實現(xiàn), 是數(shù)據(jù)庫層面的強一致性事務實現(xiàn).
兩階段提交, 常見的標準是XA等. 例如Oracle的數(shù)據(jù)庫支持XA, MySQL從5.5開始支持XA.
下圖是兩階段提交的示意圖:
圖的上半是兩階段提交成功的演示, 下半是兩階段提交失敗的演示. 關于兩階段提交網(wǎng)上有很多經(jīng)典的講解, 這里就不細說了, 可以參考前面的鏈接.
優(yōu)點
依賴數(shù)據(jù)庫服務提供商的XA實現(xiàn)來使用2PC, 無需像TCC那樣每個服務都需要手工編寫TCC接口實現(xiàn)類.
缺點
事務管理器單點失敗
高并發(fā)不適用, 資源加鎖時間較長, 無法靈活控制鎖粒度(db層面的鎖在2PC期間會一直被持有, 相較于TCC而言不靈活, 因為無法在tcc的中間階段解鎖.).
TCC (Try-Confirm-Cancle)
TCC是應用層的2PC, 具有最終一致性.
以上圖中的A->B實時匯款服務為例. 假設匯款服務和收款服務位于兩個不同的微服務中.
首先服務主調方充當事務管理器的角色, 注冊匯款收款服務的TCC接口.
事務開始, 進入TCC事務中的TRY階段.
調用匯款服務的try接口, 檢查A賬戶有效性(不在凍結狀態(tài)), 余額充足性, 并扣減轉賬金額.
調用收款服務的try接口, 檢查B賬戶的有效性(不為凍結狀態(tài)).
檢查所有被調服務的try返回值:
如果任一服務try失敗, 那么會自動調用所有服務對應的cancel方法, 對于A賬戶, 就是將余額加回; 對于B賬戶, 不做任何操作.
如果所有服務的try均成功, 那么會自動調用所有服務對應的confirm方法, 對于A賬戶, 不做任何操作; 對于B賬戶, 增加匯款金額
注意: 如果任一cancel或confirm失敗, 需要不斷重試直到成功或人工介入.
事務結束.
優(yōu)點
對比與前面提到的2PC, 主要優(yōu)勢是:
可自由控制鎖粒度(在應用層控制);
缺點
事務管理器單點失敗.
每個服務都要實現(xiàn)TCC接口, 較為復雜.
若允許并發(fā)操作, Confirm和Cancel操作無法冪等(可通過額外信息例如唯一事務id實現(xiàn)).
因為數(shù)據(jù)庫級別的事務不允許臟讀, 不存在數(shù)據(jù)一致性問題, 所以數(shù)據(jù)庫級別的rollback設計是冪等的; 而TCC為了避免數(shù)據(jù)一致性問題, 只能通過補償型操作實現(xiàn). 這就導致Confirm和Cancel操作本身不可能冪等, 解決方案有兩種:
通過事務id操作去重;
在confirm或cancel階段, 只有明確收到confirm或cancel的失敗反饋才能重試, 否則需要log而后人工介入.
適用場景
嚴格一致性
執(zhí)行時間短
實時性要求高
舉例: 紅包, 收付款, 實時匯款業(yè)務.
異步確保型
通過將一系列同步的事務操作變?yōu)榛谙?zhí)行的異步操作, 避免了分布式事務中的同步阻塞操作的影響.
這個方案真正實現(xiàn)了兩個服務的解耦, 解耦的關鍵就是異步消息和補償性事務.
這里以一個例子作為講解:
執(zhí)行步驟如下:
MQ發(fā)送方發(fā)送遠程事務消息到MQ Server;
MQ Server給予響應, 表明事務消息已成功到達MQ Server.
MQ發(fā)送方Commit本地事務.
若本地事務Commit成功, 則通知MQ Server允許對應事務消息被消費; 若本地事務失敗, 則通知MQ Server對應事務消息應被丟棄.
若MQ發(fā)送方超時未對MQ Server作出本地事務執(zhí)行狀態(tài)的反饋, 那么需要MQ Servfer向MQ發(fā)送方主動回查事務狀態(tài), 以便進一步處理未投遞的事務消息(丟棄或投遞).
當?shù)弥镜厥聞請?zhí)行成功時, MQ Server允許MQ訂閱方消費本條事務消息.
消費者消費完之后, 需要ack到MQ Server, 之后事務消息才能從MQ Server刪除. 否則消費者需要一直重試, 直到成功或者人工介入.
注意事項
消息中間件在系統(tǒng)中扮演一個重要的角色, 所有的事務消息都需要通過它來傳達, 所以消息中間件也需要支持HAC來確保事務消息不丟失.
根據(jù)業(yè)務邏輯的具體實現(xiàn)不同,還可能需要對消息中間件增加消息不重復, 不亂序等其它要求.
適用場景
執(zhí)行周期較長
實時性要求不高
例如:
非實時匯款業(yè)務
退貨/退款業(yè)務
財務, 賬單統(tǒng)計業(yè)務(先發(fā)送到消息中間件, 而后可進行批量記賬)
最大努力通知型
這是分布式事務中要求最低的一種, 也可以通過消息中間件實現(xiàn), 與前面異步確保型操作不同的一點是, 在消息由MQ Server投遞到消費者之后, 允許在達到最大重試次數(shù)之后直接結束事務, 無需人工介入確保成功.
優(yōu)點
高并發(fā), 低耦合
缺點
不支持回滾;
適用場景
交易結果消息的通知等.
SAGA
將一個大事務拆成一串小事務, 分段提交和回滾.
可能的執(zhí)行序列:
成功: T1, T2, T3, …, Tn;
失敗: T1, T2, , T3, …, Tn-1, Cn-1, Cn-2, Cn-3, …, C1
缺點
有數(shù)據(jù)一致性問題:
舉個例子, 定義:
T1=扣100元 T2=給用戶加一瓶水 T3=減庫存一瓶水
C1=加100元 C2=給用戶減一瓶水 C3=給庫存加一瓶水
如果在T3失敗進行回滾, 此時用戶已經(jīng)把水喝了, 那么就會造成回滾失敗, 出現(xiàn)數(shù)據(jù)一致性問題. 根本原因是沒有了tcc的try階段預留資源導致的. 解決方案就是要么在所有資源上加鎖, 要么嚴格控制t的順序, 將回滾困難的放在最后.
小結
不管是同步事務中的事務管理器(協(xié)調者), 還是異步事務中使用的消息中間件,若要達到一致性保證,都需要使用帶有同步復制語義的HAC提供的高可用和高可靠特性,這些都是以性能為代價的,無疑成為了SOA架構中的典型性能瓶頸之一.
不同方案對比
本文鏈接: http://blog.csdn.net/congyihao/article/details/70195154
參考鏈接
支付寶運營架構中柔性事務指的是什么?
分布式服務的事務如何處理?
理解分布式事務的兩階段提交2pc
阿里云消息隊列MQ-發(fā)送事務消息
Github: tcc-transaction
————————————————
版權聲明:本文為CSDN博主「congyh」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權協(xié)議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/congyihao/article/details/70195154
總結
以上是生活随笔為你收集整理的微服务--分布式事务的实现方法及替代方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 买股票好还是买基金好?主要从以下几点考虑
- 下一篇: 第一节 特有标签