分布式事务理论-二阶段提交(Two-phase Commit)
1 2PC
兩階段提交協議為了保證分布在不同節點上的分布式事務的一致性,我們需要引入一個協調者來管理所有的節點,負責各個本地資源的提交和回滾,并確保這些節點正確提交操作結果,若提交失敗則放棄事務。
2.1 XA 協議
XA 是一個分布式事務協議,規定了事務管理器和資源管理器接口。因此,XA 協議可以分為兩部分,即事務管理器和本地資源管理器。
- 事務管理器作為協調者,負責各個本地資源的提交和回滾;
- 資源管理器就是分布式事務的參與者.其中資源管理通常是 數據庫。
基于 XA 協議的二階段提交方法中,二階段提交協議(The two-phase commit protocol,2PC),用于保證分布式系統中事務提交時的數據一致性,是 XA 在全局事務中用于協調多個資源的機制。
2.2 二階段提交
分為投票和提交兩個階段。
?
投票為第一階段:
- 1 協調者(Coordinator,即事務管理器)會向事務的參與者(Cohort,即本地資源管理器)發起執行操作的 CanCommit 請求,并等待參與者的響應.
- 2 參與者接收到請求后,會執行請求中的事務操作,記錄日志信息(包含事務執行前的鏡像),同時鎖定當前記錄。參與者執行成功,則向協調者發送“Yes”消息,表示同意操作;若不成功,則發送“No”消息,表示終止操作。
- 3 當所有的參與者都返回了操作結果(Yes 或 No 消息)后,系統進入了提交階段。
提為第二階段:
協調者會根據所有參與者返回的信息向參與者發送 DoCommit 或 DoAbort 指令
- 若協調者收到的都是“Yes”消息,則向參與者發送“DoCommit”消息,參與者會完成剩余的操作并釋放資源,然后向協調者返回“HaveCommitted”消息;
- 如果協調者收到的消息中包含“No”消息,則向所有參與者發送“DoAbort”消息,此時發送“Yes”的參與者則會根據之前執行操作時的回滾日志對操作進行回滾,然后所有參與者會向協調者發送“HaveCommitted”消息;
- 協調者接收到“HaveCommitted”消息,就意味著整個事務結束了。
2.3 2PC問題
同步阻塞問題:二階段提交算法在執行過程中,所有參與節點都是事務阻塞型的。也就是說,當本地資源管理器占有臨界資源時,其他資源管理器如果要訪問同一臨界資源,會處于阻塞狀態。
協調者單點故障導致參與者長期阻塞問題:基于 XA 的二階段提交算法類似于集中式算法,一旦事務管理器發生故障,整個系統都處于停滯狀態。尤其是在提交階段,一旦事務管理器發生故障,資源管理器會由于等待管理器的消息,而一直鎖定事務資源,導致整個系統被阻塞。
數據不一致問題:在提交階段,當協調者向參與者發送 DoCommit 請求之后,如果發生了局部網絡異常,或者在發送提交請求的過程中協調者發生了故障,就會導致只有一部分參與者接收到了提交請求并執行提交操作,但其他未接到提交請求的那部分參與者則無法執行事務提交。于是整個分布式系統便出現了數據不一致的問題。
二階段無法解決的問題:協調者再發出DoCommit 消息之后宕機,而唯一接收到這條消息的參與者同時也宕機了。那么即使協調者通過選舉協議產生了新的協調者,這條事務的狀態也是不確定的,沒人知道事務是否被已經提交。
3 3PC
三階段提交協議(Three-phase commit protocol,3PC),是對二階段提交(2PC)的改進。為了解決兩階段提交的同步阻塞和數據不一致問題,三階段提交引入了超時機制和準備階段。
超時機制
同時在協調者和參與者中引入超時機制。如果協調者或參與者在規定的時間內沒有接收到來自其他節點的響應,就會根據當前的狀態選擇提交或者終止整個事務。
準備階段
在第一階段和第二階段中間引入了一個準備階段,也就是在提交階段之前,加入了一個預提交階段。在預提交階段排除一些不一致的情況,保證在最后提交之前各參與節點的狀態是一致的。
3.1 三階段提交
?
CanCommit 階段
協調者向參與者發送請求操作(CanCommit 請求),詢問參與者是否可以執行事務提交操作,然后等待參與者的響應;參與者收到 CanCommit 請求之后,回復 Yes,表示可以順利執行事務;否則回復 No。(我個人理解類似做TCC中Try操作)
?
PreCommit 階段
協調者根據參與者的回復情況,來決定是否可以進行 PreCommit 操作 或 中斷事務。
如果所有參與者回復的都是“Yes”,那么協調者就會執行事務的預執行:
- 發送預提交請求。協調者向參與者發送 PreCommit 請求,進入預提交階段。
- 事務預提交。參與者接收到 PreCommit 請求后執行事務操作,并將 Undo 和 Redo 信息記錄到事務日志中,同時鎖定當前記錄。
- 響應反饋。如果參與者成功執行了事務操作,則返回 ACK 響應,同時開始等待最終指令
如果任何一個參與者向協調者發送了“No”消息,或者等待超時之后,協調者都沒有收到參與者的響應,就執行中斷事務的操作:
- 發送中斷請求。協調者向所有參與者發送“Abort”消息。
- 中斷事務。參與者收到“Abort”消息之后,或超時后仍未收到協調者的消息,執行事務的中斷操作。
DoCommit 階段
協調者根據參與者的回復情況,來決定是否可以進行 DoCommit 操作 或 中斷事務。
如果所有參與者回復的都是“Yes”,那么協調者就會執行事務的提交:
- 發送提交請求。協調者接收到所有參與者發送的 Ack 響應,從預提交狀態進入到提交狀態,并向所有參與者發送 DoCommit 消息。
- 事務提交。參與者接收到 DoCommit 消息之后,正式提交事務。完成事務提交之后,釋放所有鎖住的資源。
- 響應反饋。參與者提交完事務之后,向協調者發送 Ack 響應。
- 完成事務。協調者接收到所有參與者的 Ack 響應之后,完成事務。
如果任何一個參與者向協調者發送了“No”消息,或者協調者等待超時之后,協調者都沒有收到參與者的響應,就執行中斷事務的操作:
- 發送中斷請求。協調者向所有參與者發送 Abort 請求。
- 事務回滾。參與者接收到 Abort 消息之后,利用其在 PreCommit 階段記錄的 Undo 信息執行事務的回滾操作,并釋放所有鎖住的資源。
- 反饋結果。參與者完成事務回滾之后,向協調者發送 Ack 消息。
- 中斷事務。協調者接收到參與者反饋的 Ack 消息之后,執行事務的中斷,并結束事務。
。
當參與者PreCommit 階段向協調者發送 Ack 消息后,如果長時間沒有得到協調者的響應,在默認情況下,參與者會自動將超時的事務進行提交,不會像兩階段提交那樣被阻塞住
?
3.2 如何解決協調者單點故障導致參與者長期阻塞
由于存在超時機制,即使協調者發生故障,參與者無法及時收到來自協調者的信息之后,他會默認執行commit。避免參與者長期阻塞。
3.3 同步阻塞問題
3PC會在2階段到3階段間阻塞,2PC會在1階段到2階段整個事務過程中阻塞,因而總體來說3PC并不能不阻塞,只是最大限度減少了阻塞的時間。同時安裝5.2也能夠解決協調者單點故障導致參與者長期阻塞的問題
3.4 數據不一致問題
3PC和2PC都無法解決數據一致的問題,不過3PC存在超時會通過超時保證協調者和參與者在提交階段無法通信過程中最終一致,而不需人工介入。
4 小結
?
?
總結
以上是生活随笔為你收集整理的分布式事务理论-二阶段提交(Two-phase Commit)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Gossip协议详解
- 下一篇: decltype 和 auto