二階段提交
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” 操作。