1. 程式人生 > 其它 >二階段提交

二階段提交

why:

  栗子:假設一個人要從 A 銀行向 B 銀行進行跨行轉賬 100 元。

  希望:兩個操作( -100 和 + 100),它們是一個事務, 要麼同時成功, 要麼同時失敗 。即:原子性的提交協議(Atomic Commit Protocol)

 

what:

  原子性提交協議(有2個特徵):

    安全性:任意一方 commit, 所有人必須都 commit;任意一方中斷,則所有人都不 commit

    存活性:沒有宕機或失敗發生時, A 和 B 都能提交則提交;發生失敗時,能夠最終一致性結果(成功/失敗), 予以響應, 不能一直等待

 

  二階段提交協議

      

 

    

 

    上述流程的核心點:

      當 TC 收到 A 和 B 響應 “Yes” 後, 做出了 “commit” 的決定, 向 A /B 傳送指令, 並不需要再等待 A/B 的響應, 可以直接向 client 返回成功。

    操作的保證點:當 A/B 返回 Yes 後, 就代表 A 和 B 都做好了提交準備, 只要 TC 決定要提交,即使 A/B 宕機, 沒有收到 TC 的 Commit 指令, 只要 A/B 被修復重啟, A 和 B 都必須有能力成功完成提交操作。

 

  二階段提交的安全性

    協調者 TC,作為一箇中心, 統一收集了 A 和 B 是否有意願(有能力)進行 commit;

    協調者 TC 強制保證了, A, B 雙方必須都有意願提交時, 才進行 commit;

 

  二階段提交的存活性:

    注意:協議無法滿足存活性。

    可能面臨哪些問題:

      a、響應超時。 可能原因:其他結點故障了;網路情況不好, 資料包丟失了或網路乾脆中斷了;

      b、重啟。節點宕機, 重啟以後, 如何恢復被中斷的操作;

 

    等帶響應超時應對

      1、TC 需要等待 A 和 B 返回 “yes”/“no” 超時:

                    

        對策:採取了非常保守的方案。

          此時TC 還沒有傳送過任何 “commit” 指令,則此時TC可以安全地發起終止 “abort” 指令, 放棄 commit。

 

      2、A 和 B 需要等待 TC 傳送 “commit”/ “abort” 指令, 才能進行下一步操作(等待):

             

 

 

        對策:B 為例進行考慮( A 的情形完全對稱)

          a、如果 B 之前回復的是 “no” , 那此時, B 直接abort。 因為 TC 即使收到了響應,也是“abort”;

          b、B 之前回復了 “Yes”,則不能“abort”,也不能commit。因為A可能也yes了,並且A收到commit,只是B沒收到,而應該commit;或者A回覆了NO,而應該abort。

            對策:B針對這種情形發起一輪終止協議操作(Termination Protocol)

        

 

         超時終止協議

           B向A諮詢

            B沒有響應:則B只能等待(TC恢復,再查詢TC);

            A收到“commit”/ “abort” 指令:B跟隨;

            A沒回復 “yes”/“no”:A、B直接abort。(TC超時後,也會下發abort);

            A回覆NO:A、B直接abort;

            A回覆yes:B則只能等TC信(TC恢復,再查詢TC);(原因:A 和 B 可能都 “Yes”,只是A、B沒收到,但是也就OK於client;TC可能等待超時,只是abort沒到 )

 

       宕機重啟應對

        基本原則: 一旦 TC 決定了 commit , 那麼任意一個結點都不允許發生回滾

 

        方案:所有的結點, 都能知道他們在宕機前的狀態是什麼, 那就有如下幾種解決方案:

          a、A 或 B 相互發起之前描述的終止協議 Termination Protocol, 即相互詢問是否知道事務已經交;

          b、A 和 B 也可以向 TC 發起狀態查詢操作, TC 可能知道事務是否已經提交;

 

        具體措施:所有節點傳送任何資訊給其他結點, 一定要先行將自己要回復的內容寫入磁碟

           TC 而言, 在向 A 和 B 傳送 “commit” 指令前, 一定要先行將 “commit” 成功記錄到磁碟;

           A/B 而言, 在向 TC 傳送 “yes” 之前, 一定要先行將 “yes” 記錄成功記錄到磁碟;

 

        重啟之後就可以進行如下的操作:

          a、對於TC, 重啟以後, 如果發現磁碟中沒有記錄 “commit” , 那就可以直接進行 “abort” 操作;

          b、 A 或者 B , 重啟以後, 如果發現磁碟中沒有記錄 “yes” , 那就可以直接進行 “abort” 操作;

          c、A或者 B, 重啟以後, 如果發現磁碟中有 “yes” 記錄, 那就可以發起終止協議 “termination protocol”;

          d、TC, A, B 都發生了重啟操作, 只要當 3 個結點都恢復以後, 就可以向 TC 發起查詢, 檢視TC 的磁碟中是否存在 “commit” 記錄, 如果存在, 則均可進行 “commit” 操作。