柔性事務知足BASE理論(基本可用,最終一致)。mysql
剛性事務知足ACID理論。sql
在分佈式事務當中主要討論的是柔性事務的處理方式。數據庫
柔性事務分爲:服務器
兩階段提交(2-Phase Commit, 2PC)是一種比較簡單的分佈式一致性協議。網絡
2PC協議中,每一個事務須要一個協調者來協調各個參與者。每一個事務分爲兩步執行。分佈式
2PC是一種簡單的一致性協議,它存在一些問題:優化
參與者在完成階段一的事務執行後等待協調者的下一個請求,若協調者超時則能夠自行放棄事務。日誌
這種方案仍然有沒法保證一致性的缺點,但並不會出現某些資料所述一直鎖定資源,沒法繼續的狀況。code
三階段提交協議(3-Phase Commit, 3PC)進一步將事務請求分爲兩個階段,能夠解決2PC協議阻塞的問題但沒法解決單點服務和不一致的問題。blog
3PC協議下事務分三步提交:
三階段提交協議在CanCommit階段不鎖定資源,解決了阻塞下降吞吐量的問題。
若某個參與者進入 PreCommit 後始終未收到協調者的進一步指令則會自動提交,該策略必定程度上避免協調者單點服務問題。
可是 3PC 仍然沒法解決數據不一致問題。
TCC型事務(Try/Confirm/Cancel)能夠歸爲補償型。補償型的例子,在一個長事務( long-running )中 ,一個由兩臺服務器一塊兒參與的事務,服務器A發起事務,服務器B參與事務,B的事務須要人工參與,因此處理時間可能很長。若是按照ACID的原則,要保持事務的隔離性、一致性,服務器A中發起的事務中使用到的事務資源將會被鎖定,不容許其餘應用訪問到事務過程當中的中間結果,直到整個事務被提交或者回滾。這就形成事務A中的資源被長時間鎖定,系統的可用性將不可接受。
WS-BusinessActivity提供了一種基於補償的long-running的事務處理模型。仍是上面的例子,服務器A的事務若是執行順利,那麼事務A就先行提交,若是事務B也執行順利,則事務B也提交,整個事務就算完成。可是若是事務B執行失敗,事務B自己回滾,這時事務A已經被提交,因此須要執行一個補償操做,將已經提交的事務A執行的操做做反操做,恢復到未執行前事務A的狀態。這樣的SAGA事務模型,是犧牲了必定的隔離性和一致性的,可是提升了long-running事務的可用性。
TCC 將事務提交分爲 Try - Confirm - Cancel 3個操做。
TCC優勢:讓應用本身定義數據庫操做的粒度,使得下降鎖衝突、提升吞吐量成爲可能。
TCC不足之處:
流程:
try
給全部參與者try
, 嘗試預留資源, 並返回給發起者commit
/cancel
指令給參與者commit
/cancel
, 並返回執行結果例子:
購買從 廣州到北京的機票, 由於購買不到直達的機票, 因此購買 廣州->上海->北京, 在上海中轉
廣州->上海 南航
上海->北京 東航
由於不屬於同一個航空公司, 因此須要分別購買
若是訂票系統依次購買, 可能存在第一家購買成功, 第二家購買失敗, 這事不能接受的
因此訂票系統先向兩家航空公司發送請求, 肯定是否有足夠的餘票, 並讓對方預留票
與 2PC 的比較
TCC | 2PC | |
---|---|---|
第一階段 | Try: 請求原業務方預留資源 | Prepare: 詢問是否能夠進行提交 |
段二階段(成功) | Confirm:確認執行 | Commit: 提交事務 |
第二階段(失敗) | Cancel: 取消執行資源操做 | Rollback: 回滾事務 |
2PC 是資源層面的, 基於數據庫底層 (好比mysql的xa事務), 開發者不可感知, 無侵入性
TCC 是業務層面, 開發者可感知, 能夠根據業務對事務作特定的優化
存在的問題
存在和 2PC 相似的問題
若是發起者發送 confirm
過程失敗, 致使有的參與者接收到指令, 執行了comfirm
而有的參與者因爲沒有接收到指令, 而由於timeout
, 執行了cancel
破壞了整個系統的數據一致性
背景:
一直以來, 執行數據庫事務都是使用 LLT (long lived transaction), 即跨越多個數據庫事務的事務, 一次性完成全部事務, 其中不容許其餘事務打斷, 使用這種機制, 能夠保證數據庫的數據一致性
可是會帶來幾個問題:
簡述
而 Saga 模式是爲了彌補 LLT 的缺陷
Saga 模式將一個長事務分割多個子事務 (saga), 而後逐一執行每個子事務, 一旦其中一環出現了錯誤, 經過補償機制, 一一回滾以前已經執行的事務
$$
T1 T2 T3...Tj...Tn\
transaction\
C1 C2 C3...Cj...Cn \
compensating transaction
$$
整個流程有如下狀況:
$$
T1 → T2 → T3 →...→...→ Tn
$$
$$
T1 → T2 → T3 →...→...→ Tj → Cj →...→ C3 → C2 → C1
$$
注意點:
例子
假設一我的須要進行如上的飛機票預訂, 訂票系統須要向四個航空公司發出訂票請求
若是其中任何一個環節出現了問題, 就經過補償機制, 將以前預訂的票逐一退訂
與TCC的比較
try
接口, 只須要能夠commit
和rollback