??在分布式系統(tǒng)中,當一個事務操作需要跨越多個分布式節(jié)點時,為了保持事務的ACID特性,就出現(xiàn)了“協(xié)調(diào)者(Coordinator)”來統(tǒng)一調(diào)度所有分布式節(jié)點的執(zhí)行邏輯,而被調(diào)度的分布式節(jié)點則被稱為“參與者(Cohort)”。協(xié)調(diào)者(Coordinator)負責調(diào)度參與者(Cohort)的行為,并最終決定這些參與者(Cohort)是否把事務真正進行提交?;谶@個思想,衍生出2PC和3PC兩種協(xié)議。
一. 2PC (Two-Phase Commit)
??2PC(Two-Phase Commit)為二階段提交,為了分布式系統(tǒng)下所有節(jié)點操作事務能夠保存原子性和一致性而設計的一種算法。主要應用在關系型數(shù)據(jù)庫來完成分布式事務處理,利用該協(xié)議可以方便地利用協(xié)調(diào)者(Coordinator)進行統(tǒng)一的事務提交和回滾,從而能夠有效的保證分布式數(shù)據(jù)一致性。
2PC的兩階段
階段一(提交請求階段)
各參與者(Cohort)投票表明是否要繼續(xù)執(zhí)行接下來的事務提交操作:
- 協(xié)調(diào)者(Coordinator)節(jié)點向所有參與者(Cohort)節(jié)點詢問是否可以執(zhí)行提交操作,并開始等待各參與者(Cohort)節(jié)點的響應。
- 參與者(Cohort)節(jié)點執(zhí)行詢問發(fā)起為止的所有事務操作,并將Undo信息和Redo信息寫入日志。
- 各參與者(Cohort)節(jié)點響應協(xié)調(diào)者(Coordinator)節(jié)點發(fā)起的詢問。如果參與者(Cohort)節(jié)點的事務操作實際執(zhí)行成功,則它返回一個"同意"消息;如果參與者(Cohort)節(jié)點的事務操作實際執(zhí)行失敗,則它返回一個"中止"消息。
階段二(提交執(zhí)行階段)
協(xié)調(diào)者(Coordinator)會根據(jù)參與者(Cohort)的反饋情況來決定是否可以進行事務提交操作,可分為事務提交以及事務中斷兩種情況 。
事務提交:
當協(xié)調(diào)者(Coordinator)節(jié)點從所有參與者(Cohort)節(jié)點獲得的對應的消息都為"Yes"時:
- 協(xié)調(diào)者(Coordinator)節(jié)點向所有參與者(Cohort)節(jié)點發(fā)出"Commit"的請求。
- 參與者(Cohort)節(jié)點收到Commit請求后,正式執(zhí)行事務操作,并釋放在整個事務期間內(nèi)占用的資源。
- 參與者(Cohort)節(jié)點向協(xié)調(diào)者(Coordinator)節(jié)點發(fā)送"Ack"消息,確認完成。
-
協(xié)調(diào)者(Coordinator)節(jié)點收到所有參與者(Cohort)節(jié)點反饋的"Ack"完成消息后,完成事務。
image
事務中斷:
如果任一參與者(Cohort)節(jié)點在第一階段返回的響應消息為"No",或者協(xié)調(diào)者(Coordinator)節(jié)點在第一階段的詢問超時之前無法獲取所有參與者(Cohort)節(jié)點的響應消息時:
- 協(xié)調(diào)者(Coordinator)節(jié)點向所有參與者(Cohort)節(jié)點發(fā)出"Rollback"請求。
- 參與者(Cohort)節(jié)點接收到"Rollback"請求,利用之前寫入的Undo信息執(zhí)行回滾,并釋放在整個事務期間內(nèi)占用的資源。
- 參與者(Cohort)節(jié)點向協(xié)調(diào)者(Coordinator)節(jié)點發(fā)送"Ack"回滾完成消息。
- 協(xié)調(diào)者(Coordinator)節(jié)點收到所有參與者(Cohort)節(jié)點反饋的"Ack"回滾完成消息后,取消事務。
缺點
同步阻塞問題:執(zhí)行過程中,所有參與者(Cohort)節(jié)點都是事務阻塞型。各個參與者(Cohort)在等待其他參與者響應的過程中,將無法進行其他任務操作;
單點故障:由于協(xié)調(diào)者(Coordinator)的重要性,一旦協(xié)調(diào)者(Coordinator)發(fā)生故障,參與者(Cohort)會一直阻塞下去。特別是在階段二中,協(xié)調(diào)者(Coordinator)發(fā)生故障,那么所有的參與者(Cohort)還都處于鎖定事務資源的狀態(tài)中,而無法繼續(xù)完成事務操作。
數(shù)據(jù)不一致:在階段二中,當協(xié)調(diào)者(Coordinator)向參與者(Cohort)發(fā)送commit請求之后,發(fā)生了局部網(wǎng)絡異?;蛘咴诎l(fā)送commit請求過程中協(xié)調(diào)者(Coordinator)出現(xiàn)問題,將導致只有一部分參與者(Cohort)收到commit請求,以至于這部分參與者(Cohort)接到commit請求之后就會執(zhí)行commit操作,而其他部分未接到commit請求的參與者(Cohort)則無法執(zhí)行事務提交。于是整個分布式系統(tǒng)便出現(xiàn)了數(shù)據(jù)部一致性的現(xiàn)象。
不具備完善容錯機制:任意一個節(jié)點的失敗都會導致整個事務的失敗。參與者(Cohort)宕機或者超時,都需要協(xié)調(diào)者(Coordinator)自身機制去判斷或者協(xié)調(diào)者(Coordinator)在發(fā)出commit消息之后宕機,而唯一接收到這條消息的參與者(Cohort)同時也宕機了。那么即使協(xié)調(diào)者(Coordinator)通過選舉協(xié)議產(chǎn)生了新的協(xié)調(diào)者,這條事務的狀態(tài)也是不確定的,沒人知道事務是否被已經(jīng)提交。
二. 3PC (Three-Phase Commit)
??3PC (Three-Phase Commit)為了改進2PC中出現(xiàn)的同步阻塞、單點問題、腦裂以及保守的容錯機制缺陷提出的三階段提交協(xié)議,分為CanCommit、PreCommit和doCommit三階段進行事務處理協(xié)議。如下圖:
階段一:CanCommit
- 協(xié)調(diào)者(Coordinator)節(jié)點向所有參與者(Cohort)節(jié)點詢問是否可以執(zhí)行提交操作,并開始等待各參與者(Cohort)節(jié)點的響應。
- 協(xié)調(diào)者(Coordinator)向參與者(Cohort)發(fā)送commit請求,參與者(Cohort)如果可以提交就返回Yes響應進入預備狀態(tài),否則返回No響應。
階段二:PreCommit
??協(xié)調(diào)者(Coordinator)根據(jù)參與者(Cohort)的反應情況來決定是否可以繼續(xù)事務的PreCommit操作。根據(jù)響應情況,有以下兩種可能執(zhí)行提交和中斷事務:
執(zhí)行提交:
協(xié)調(diào)者(Coordinator)從所有的參與者(Cohort)獲得的反饋都是Yes響應,那么就會進行事務的預執(zhí)行:
- 發(fā)送預提交請求::協(xié)調(diào)者(Coordinator)向參與者(Cohort)發(fā)送PreCommit請求,并進入Prepared階段。
- 事務預提交:參與者(Cohort)接收到PreCommit請求后,會執(zhí)行事務操作,并將undo和redo信息記錄到事務日志中。
- 響應反饋:如果參與者(Cohort)成功的執(zhí)行了事務操作,則返回ACK響應,同時開始等待最終指令。
中斷事務:
有任何一個參與者(Cohort)向協(xié)調(diào)者(Coordinator)發(fā)送了No響應,或者等待超時之后,Coordinator都沒有接到參與者(Cohort)的響應,那么就中斷事務:
- 發(fā)送中斷請求:協(xié)調(diào)者(Coordinator)向所有參與者(Cohort)發(fā)送abort請求。
- 中斷事務:參與者(Cohort)收到來自協(xié)調(diào)者(Coordinator)的abort請求之后(或超時之后,仍未收到參與者(Cohort)的請求),執(zhí)行事務的中斷。
階段三:DoCommit
該階段進行真正的事務提交,也可以分為以下兩種情況執(zhí)行提交和中斷事務:
執(zhí)行提交
- 發(fā)送提交請求:協(xié)調(diào)者(Coordinator)接收到參與者(Cohort)t發(fā)送的ACK響應,那么他將從預提交狀態(tài)進入到提交狀態(tài)。并向所有參與者(Cohort)發(fā)送doCommit請求。
- 事務提交:參與者(Cohort)接收到doCommit請求之后,執(zhí)行正式的事務提交。并在完成事務提交之后釋放所有事務資源。
- 響應反饋:事務提交完之后,向協(xié)調(diào)者(Coordinator)發(fā)送ACK響應。
- 完成事務:協(xié)調(diào)者(Coordinator)接收到所有參與者(Cohort)的ACK響應之后,完成事務。
中斷事務:
協(xié)調(diào)者(Coordinator)正常,接收到參與者(Cohort)發(fā)送的反饋No響應,或者沒有收到到Ack響應(可能是接受者發(fā)送的不是ACK響應,也可能響應超時),那么就會執(zhí)行中斷事務。
- 發(fā)送中斷請求:協(xié)調(diào)者(Coordinator)向所有參與者節(jié)點發(fā)送abort請求;
- 事務回滾:參與者(Cohort)接收到abort請求后,利用記錄的Undo信息進行事務回滾操作,并在回滾完成后釋放整個事務執(zhí)行期間占用的資源。
- 反饋事務回滾結果:參與者(Cohort)在完成事務回滾之后,向協(xié)調(diào)者(Coordinator)發(fā)送Ack消息。
- 中斷事務:協(xié)調(diào)者(Coordinator)接收所有參與者(Cohort)的反饋Ack消息后,中斷事務。
優(yōu)缺點
- 優(yōu)點: 降低參與者阻塞范圍,并能夠在出現(xiàn)單點故障后繼續(xù)達成一致
- 缺點: 引入preCommit階段,在這個階段如果出現(xiàn)網(wǎng)絡分區(qū),協(xié)調(diào)者無法與參與者正常通信,參與者依然會進行事務提交,造成數(shù)據(jù)不一致。
三. 總結
??無論是二階段提交還是三階段提交都從不同程度地解決了分布式數(shù)據(jù)一致性問題,使用范圍非常廣泛,但都無法徹底解決分布式的一致性問題。還有一種一致性協(xié)議Paxos算法,解決了無限期等待問題,也解決了“腦裂”問題,通俗易懂的Paxos原理可查看文章《通俗易懂的Paxos算法-基于消息傳遞的一致性算法》。