出處:https://github.com/clsaa/Distributed-Transaction-Notes。
作者總結得很全面,做個筆記搬運。
一、 兩階段提交(2PC)
二階段提交(Two-phaseCommit)是指,在計算機網絡以及數據庫領域內,為了使基於分布式系統架構下的所有節點在進行事務提交時保持一致性而設計的一種算法(Algorithm)。通常,二階段提交也被稱為是一種協議(Protocol))。在分布式系統中,每個節點雖然可以知曉自己的操作時成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的組件來統一掌控所有節點(稱作參與者)的操作結果並最終指示這些節點是否要把操作結果進行真正的提交(比如將更新后的數據寫入磁盤等等)。因此,二階段提交的算法思路可以概括為:參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情報決定各參與者是否要提交操作還是中止操作。
- 所謂的兩個階段是指:第一階段:准備階段(投票階段)和第二階段:提交階段(執行階段)。
1. 准備階段
- 事務協調者(事務管理器)給每個參與者(資源管理器)發送Prepare消息,每個參與者要么直接返回失敗(如權限驗證失敗),要么在本地執行事務,寫本地的redo和undo日志,但不提交,到達一種“萬事俱備,只欠東風”的狀態。
- 一般講准備階段分為以下三個階段
- 協調者節點向所有參與者節點詢問是否可以執行提交操作(vote),並開始等待各參與者節點的響應。
- 參與者節點執行詢問發起為止的所有事務操作,並將Undo信息和Redo信息寫入日志。(注意:若成功這里其實每個參與者已經執行了事務操作)
- 各參與者節點響應協調者節點發起的詢問。如果參與者節點的事務操作實際執行成功,則它返回一個”同意”消息;如果參與者節點的事務操作實際執行失敗,則它返回一個”中止”消息。
2. 提交階段
- 如果協調者收到了參與者的失敗消息或者超時,直接給每個參與者發送回滾(Rollback)消息;否則,發送提交(Commit)消息;參與者根據協調者的指令執行提交或者回滾操作,釋放所有事務處理過程中使用的鎖資源。(注意:必須在最后階段釋放鎖資源)
- 當協調者節點從所有參與者節點獲得的相應消息都為”同意”時:
- 協調者節點向所有參與者節點發出”正式提交(commit)”的請求。
- 參與者節點正式完成操作,並釋放在整個事務期間內占用的資源。
- 參與者節點向協調者節點發送”完成”消息。
- 協調者節點受到所有參與者節點反饋的”完成”消息后,完成事務。
- 如果任一參與者節點在第一階段返回的響應消息為”中止”,或者 協調者節點在第一階段的詢問超時之前無法獲取所有參與者節點的響應消息時:
- 協調者節點向所有參與者節點發出”回滾操作(rollback)”的請求。
- 參與者節點利用之前寫入的Undo信息執行回滾,並釋放在整個事務期間內占用的資源。
- 參與者節點向協調者節點發送”回滾完成”消息。
- 協調者節點受到所有參與者節點反饋的”回滾完成”消息后,取消事務。
3. 兩階段提交的缺陷
- 同步阻塞問題。執行過程中,所有參與節點都是事務阻塞型的。當參與者占有公共資源時,其他第三方節點訪問公共資源不得不處於阻塞狀態。
- 單點故障。由於協調者的重要性,一旦協調者發生故障。參與者會一直阻塞下去。尤其在第二階段,協調者發生故障,那么所有的參與者還都處於鎖定事務資源的狀態中,而無法繼續完成事務操作。(如果是協調者掛掉,可以重新選舉一個協調者,但是無法解決因為協調者宕機導致的參與者處於阻塞狀態的問題)
- 數據不一致。在二階段提交的階段二中,當協調者向參與者發送commit請求之后,發生了局部網絡異常或者在發送commit請求過程中協調者發生了故障,這回導致只有一部分參與者接受到了commit請求。而在這部分參與者接到commit請求之后就會執行commit操作。但是其他部分未接到commit請求的機器則無法執行事務提交。於是整個分布式系統便出現了數據部一致性的現象。
- 二階段無法解決的問題:協調者再發出commit消息之后宕機,而唯一接收到這條消息的參與者同時也宕機了。那么即使協調者通過選舉協議產生了新的協調者,這條事務的狀態也是不確定的,沒人知道事務是否被已經提交。
二、 三階段提交(3PC)
- 三階段提交(Three-phase commit),也叫三階段提交協議(Three-phase commit protocol),是二階段提交(2PC)的改進版本。
1. 與兩階段提交的不同點
- 引入超時機制。同時在協調者和參與者中都引入超時機制。
- 在第一階段和第二階段中插入一個准備階段。保證了在最后提交階段之前各參與節點的狀態是一致的。
也就是說,除了引入超時機制之外,3PC把2PC的准備階段再次一分為二,這樣三階段提交就有CanCommit、PreCommit、DoCommit三個階段。
- 相對於2PC,3PC主要解決的單點故障問題,並減少阻塞,因為一旦參與者無法及時收到來自協調者的信息之后,他會默認執行commit。而不會一直持有事務資源並處於阻塞狀態。但是這種機制也會導致數據一致性問題,因為,由於網絡原因,協調者發送的abort響應沒有及時被參與者接收到,那么參與者在等待超時之后執行了commit操作。這樣就和其他接到abort命令並執行回滾的參與者之間存在數據不一致的情況。
2. CanCommit階段
- 3PC的CanCommit階段其實和2PC的准備階段很像。協調者向參與者發送commit請求,參與者如果可以提交就返回Yes響應,否則返回No響應
1.事務詢問:協調者向參與者發送CanCommit請求。詢問是否可以執行事務提交操作。然后開始等待參與者的響應。
2.響應反饋:參與者接到CanCommit請求之后,正常情況下,如果其自身認為可以順利執行事務,則返回Yes響應,並進入預備狀態。否則反饋No
3. PreCommit階段
- 假如協調者從所有的參與者獲得的反饋都是Yes響應,那么就會進行事務的預執行。
- 發送預提交請求:協調者向參與者發送PreCommit請求,並進入Prepared階段。
- 事務預提交:參與者接收到PreCommit請求后,會執行事務操作,並將undo和redo信息記錄到事務日志中。
- 響應反饋:如果參與者成功的執行了事務操作,則返回ACK響應,同時開始等待最終指令。
- 假如有任何一個參與者向協調者發送了No響應,或者等待超時之后,協調者都沒有接到參與者的響應,那么就執行事務的中斷。
- 發送中斷請求:協調者向所有參與者發送abort請求。
- 中斷事務:參與者收到來自協調者的abort請求之后(或超時之后,仍未收到協調者的請求),執行事務的中斷。
4. doCommit階段
- 執行提交
- 發送提交請求:協調接收到參與者發送的ACK響應,那么他將從預提交狀態進入到提交狀態。並向所有參與者發送doCommit請求。
- 事務提交:參與者接收到doCommit請求之后,執行正式的事務提交。並在完成事務提交之后釋放所有事務資源。
- 響應反饋:事務提交完之后,向協調者發送Ack響應。
- 完成事務:協調者接收到所有參與者的ack響應之后,完成事務。
- 中斷事務:協調者沒有接收到參與者發送的ACK響應(可能是接受者發送的不是ACK響應,也可能響應超時),那么就會執行中斷事務。
- 發送中斷請求:協調者向所有參與者發送abort請求
- 事務回滾:參與者接收到abort請求之后,利用其在階段二記錄的undo信息來執行事務的回滾操作,並在完成回滾之后釋放所有的事務資源。
- 反饋結果:參與者完成事務回滾之后,向協調者發送ACK消息
- 中斷事務:協調者接收到參與者反饋的ACK消息之后,執行事務的中斷。
在doCommit階段,如果參與者無法及時接收到來自協調者的doCommit或者rebort請求時,會在等待超時之后,會繼續進行事務的提交。(其實這個應該是基於概率來決定的,當進入第三階段時,說明參與者在第二階段已經收到了PreCommit請求,那么協調者產生PreCommit請求的前提條件是他在第二階段開始之前,收到所有參與者的CanCommit響應都是Yes。(一旦參與者收到了PreCommit,意味他知道大家其實都同意修改了)所以,一句話概括就是,當進入第三階段時,由於網絡超時等原因,雖然參與者沒有收到commit或者abort響應,但是他有理由相信:成功提交的幾率很大。 )
三、 CAP定理
1. 標准分布式事務缺陷
- 效率非常低
- 全局事務方式下,全局事務管理器(TM)通過XA接口使用二階段提交協議( 2PC )與資源層(如數據庫)進行交互。使用全局事務,數據被Lock的時間跨整個事務,直到全局事務結束。
- 2PC 是反可伸縮模式,在事務處理過程中,參與者需要一直持有資源直到整個分布式事務結束。這樣,當業務規模越來越大的情況下,2PC 的局限性就越來越明顯,系統可伸縮性會變得很差。
- 與本地事務相比,XA 協議的系統開銷相當大,因而應當慎重考慮是否確實需要分布式事務。而且只有支持 XA 協議的資源才能參與分布式事務。
2. CAP理論詳解
- CAP原則是NOSQL數據庫的基石。
- CAP原則又稱CAP定理,指的是在一個分布式系統中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性),三者不可得兼。
- 一致性(C):在分布式系統中的所有數據備份,在同一時刻是否同樣的值。(等同於所有節點訪問同一份最新的數據副本)
- 可用性(A):在集群中一部分節點故障后,集群整體是否還能響應客戶端的讀寫請求。(對數據更新具備高可用性)
- 分區容忍性(P):以實際效果而言,分區相當於對通信的時限要求。系統如果不能在時限內達成數據一致性,就意味着發生了分區的情況,必須就當前操作在C和A之間做出選擇。(容忍網絡中斷)
四、 BASE理論
BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistent(最終一致性)三個短語的簡寫,BASE是對CAP中一致性和可用性權衡的結果,其來源於對大規模互聯網系統分布式實踐的結論,是基於CAP定理逐步演化而來的,其核心思想是即使無法做到強一致性(Strong consistency),但每個應用都可以根據自身的業務特點,采用適當的方式來使系統達到最終一致性(Eventual consistency)。接下來我們着重對BASE中的三要素進行詳細講解。
- BA: Basic Availability 基本業務可用性(支持分區失敗):分布式系統在出現不可預知故障的時候,允許損失部分可用性
- 響應時間上的損失:正常情況下,一個在線搜索引擎需要0.5秒內返回給用戶相應的查詢結果,但由於出現異常(比如系統部分機房發生斷電或斷網故障),查詢結果的響應時間增加到了1~2秒。
- 功能上的損失:正常情況下,在一個電子商務網站上進行購物,消費者幾乎能夠順利地完成每一筆訂單,但是在一些節日大促購物高峰的時候,由於消費者的購物行為激增,為了保護購物系統的穩定性,部分消費者可能會被引導到一個降級頁面。
- S: Soft state 柔性狀態(狀態允許有短時間不同步,異步)
- E: Eventual consistency 最終一致性(最終數據是一致的,但不是實時一致)
- 因果一致性:因果一致性是指,如果進程A在更新完某個數據項后通知了進程B,那么進程B之后對該數據項的訪問都應該能夠獲取到進程A更新后的最新值,並且如果進程B要對該數據項進行更新操作的話,務必基於進程A更新后的最新值,即不能發生丟失更新情況。與此同時,與進程A無因果關系的進程C的數據訪問則沒有這樣的限制。
- 讀己之所寫:讀己之所寫是指,進程A更新一個數據項之后,它自己總是能夠訪問到更新過的最新值,而不會看到舊值。也就是說,對於單個數據獲取者而言,其讀取到的數據一定不會比自己上次寫入的值舊。因此,讀己之所寫也可以看作是一種特殊的因果一致性。
- 會話一致性:會話一致性將對系統數據的訪問過程框定在了一個會話當中:系統能保證在同一個有效的會話中實現“讀己之所寫”的一致性,也就是說,執行更新操作之后,客戶端能夠在同一個會話中始終讀取到該數據項的最新值。
- 單調讀一致性:單調讀一致性是指如果一個進程從系統中讀取出一個數據項的某個值后,那么系統對於該進程后續的任何數據訪問都不應該返回更舊的值。
- 單調寫一致性:單調寫一致性是指,一個系統需要能夠保證來自同一個進程的寫操作被順序地執行。
原子性(A)與持久性(D)必須根本保障
為了可用性、性能與降級服務的需要,只有降低一致性( C ) 與 隔離性( I ) 的要求
五、 柔性事務
1. 柔性事務中的服務模式
服務模式是柔性事務流程中的特殊操作實現(實現上對應業務服務要提供相應模式的功能接口),還不算是某一種柔性事務解決方案。
- 可查詢操作
- 服務操作的可標識性
- 服務操作具有全局唯一標識(可以使用業務單據號/使用系統分配的操作流水號使用操作資源的組合組合標識)
- 操作有唯一的、確定的時間
- 單筆查詢
- 使用全局唯一的服務操作標識,查詢操作執行結果
- 注意狀態判斷,小心“處理中”的狀態
- 批量查詢
- 使用時間區段與(或)一組服務操作的標識,查詢一批操作執行結果
- 服務操作的可標識性
- 冪等操作
- 冪等性:f(f(x)) = f(x)
- 冪等操作:重復調用多次產生的業務結果與調用一次產生的業務結果相同
- 實現方式一:通過業務操作本身實現冪等性
- 實現方式二:系統緩存所有請求與處理結果,檢測到重復請求之后,自動返回之前的處理結果
- TCC操作
- Try: 嘗試執行業務
- 完成所有業務檢查(一致性)
- 預留必須業務資源(准隔離性)
- Confirm:確認執行業務
- 真正執行業務
- 不作任何業務檢查
- 只使用Try階段預留的業務資源
- Confirm操作要滿足冪等性
- Cancel: 取消執行業務
- 釋放Try階段預留的業務資源
- Cancel操作要滿足冪等性
- 與2PC協議比較
- 位於業務服務層而非資源層
- 沒有單獨的准備(Prepare)階段,Try操作兼備資源操作與准備能力
- Try操作可以靈活選擇業務資源的鎖定粒度(以業務定粒度)
- 較高開發成本
- Try: 嘗試執行業務
很多人把兩階段型操作等同於兩階段提交協議2PC操作。其實TCC操作也屬於兩階段型操作。
- 可補償操作
- do: 真正執行業務
- 完成業務處理
- 業務執行結果外部可見
- compensate:業務補償
- 抵銷(或部分抵銷)正向業務操作的業務結果
- 補償操作滿足冪等性
- 約束
- 補償在業務上可行
- 由於業務執行結果未隔離、或者補償不完整帶來的風險與成本可控
- do: 真正執行業務
TCC操作中的Confirm操作和Cancel操作,其實也可以看作是補償操作
簡而言之,TCC是應用層的2PC(2 Phase Commit, 兩階段提交),如果你將應用看做資源管理器的話。
詳細來說,TCC每項操作需要做的事情如下:Try:嘗試執行業務, 完成所有業務檢查(一致性)預留必須業務資源(准隔離性); Confirm:確認執行業務, 真正執行業務不做任何業務檢查只使用Try階段預留的業務資源; Cancel:取消執行業務釋放Try階段預留的業務資源.
TCC事務的優點如下:解決了跨應用業務操作的原子性問題,在諸如組合支付、賬務拆分場景非常實用。TCC實際上把數據庫層的二階段提交上提到了應用層來實現,對於數據庫來說是一階段提交,規避了數據庫層的2PC性能低下問題。 TCC事務的缺點,主要就一個:TCC的Try、Confirm和Cancel操作功能需業務提供,開發成本高。
賬務拆分的業務場景如下,分別位於三個不同分庫的帳戶A、B、C,A和B一起向C轉帳共80元:
Try:嘗試執行業務。完成所有業務檢查(一致性):檢查A、B、C的帳戶狀態是否正常,帳戶A的余額是否不少於30元,帳戶B的余額是否不少於50元。預留必須業務資源(准隔離性):帳戶A的凍結金額增加30元,帳戶B的凍結金額增加50元,這樣就保證不會出現其他並發進程扣減了這兩個帳戶的余額而導致在后續的真正轉帳操作過程中,帳戶A和B的可用余額不夠的情況。
Confirm:確認執行業務。真正執行業務:如果Try階段帳戶A、B、C狀態正常,且帳戶A、B余額夠用,則執行帳戶A給賬戶C轉賬30元、帳戶B給賬戶C轉賬50元的轉帳操作。不做任何業務檢查:這時已經不需要做業務檢查,Try階段已經完成了業務檢查。只使用Try階段預留的業務資源:只需要使用Try階段帳戶A和帳戶B凍結的金額即可。
Cancel:取消執行業務釋放Try階段預留的業務資源:如果Try階段部分成功,比如帳戶A的余額夠用,且凍結相應金額成功,帳戶B的余額不夠而凍結失敗,則需要對帳戶A做Cancel操作,將帳戶A被凍結的金額解凍掉。 小結:到底要不要使用TCC 到底要不要使用TCC事務,取決於以下幾點:是否真正有保證跨應用業務操作的原子性需求。研發上能否投入資源開發相對應的TCC接口。
2. 最終一致性(可靠消息/異步確保型)
最終一致性是柔性事務解決方案。
- 實現
- 業務處理服務在業務事務提交前,向實時消息服務請求發送消息,實時消息服務只記錄消息數據,而不真正發送。業務處理服務在業務事務提交后,向實時消息服務確認發送。只有在得到確認發送指令后,實時消息服務才真正發送
- 業務處理服務在業務事務回滾后,向實時消息服務取消發送。消息狀態確認系統定期找到未確認發送或回滾發送的消息,向業務處理服務詢問消息狀態,業務處理服務根據消息ID或消息內容確定該消息是否有效
- 約束
- 被動方的處理結果不影響主動方的處理結果, 被動方的消息處理操作是冪等操作
- 成本
- 可靠消息系統建設成本
- 一次消息發送需要兩次請求,業務處理服務需實現消息狀態回查接口
- 優點、適用范圍
- 消息數據獨立存儲、獨立伸縮,降低業務系統與消息系統間的耦合
- 對最終一致性時間敏感度較高,降低業務被動方實現成本
- 用到的服務模式:可查詢操作、冪等操作
- 方案特點
- 兼容所有實現JMS標准的MQ中間件
- 確保業務數據可靠的前提下,實現業務數據的最終一致(理想狀態下基本是准實時一致)
3. TCC(兩階段型/補償型)
TCC(兩階段型/補償型):Try-Confirm-Cancel,柔性事務解決方案。
- 實現
- 一個完整的業務活動由一個主業務服務與若干從業務服務組成
- 主業務服務負責發起並完成整個業務活從業務服務提供TCC型業務操作
- 業務活動管理器控制業務活動的一致性,它登記業務活動中的操作, 並在業務活動提交時確認所有的TCC型操作的confirm操作,在業務活動取消時調用所有TCC型操作的cancel操作
- 成本
- 實現TCC操作的成本
- 業務活動結束時confirm或cancel操作的執行成本
- 業務活動日志成本
- 適用范圍
- 強隔離性、嚴格一致性要求的業務活動
- 適用於執行時間較短的業務(比如處理賬戶、收費等業務)
- 用到的服務模式:TCC操作、冪等操作、可補償操作、 可查詢操作
- 方案特點:
- 不與具體的服務框架耦合(在RPC架構中通用)
- 位於業務服務層,而非資源層
- 可以靈活選擇業務資源的鎖定粒度
- TCC里對每個服務資源操作的是本地事務,數據被lock的時間短,可擴展性好(可以說是為獨立部署的SOA服務而設計的)
4. 最大努力通知型(定期校對)
柔性事務解決方案。
- 實現
- 業務活動的主動方,在完成業務處理之后,向業務活動的被動方發送消息,允許消息丟失。
- 業務活動的被動方根據定時策略,向業務活動主動方查詢,恢復丟失的業務消息。
- 約束:被動方的處理結果不影響主動方的處理結果
- 成本:業務查詢與校對系統的建設成本
- 適用范圍
- 對業務最終一致性的時間敏感度低
- 跨企業的業務活動
- 用到的服務模式:可查詢操作
- 方案特點
- 業務活動的主動方在完成業務處理后,向業務活動被動方發送通知消息(允許消息丟失)
- 主動方可以設置時間階梯型通知規則,在通知失敗后按規則重復通知,直到通知N次后不再通知
- 主動方提供校對查詢接口給被動方按需校對查詢,用於恢復丟失的業務消息
- 行業應用案例:銀行通知、商戶通知等
六、 總結
1.分類總結
- 剛性事務
- XA 全局事務(標准的分布式事務)
- 柔性事務
- 可靠消息最終一致(異步確保型)
- TCC(兩階段型、補償型)
- 最大努力通知(非可靠消息 、 定期校對)
- 純補償型(略)