目錄
PreCommit(如果CanCommit階段中所有參與者都返回“Yes”)
兩階段提交(2PC)
圖片來源:https://medium.com/@balrajasubbiah/consensus-two-phase-and-three-phase-commits-4e35c1a435ac
準備階段:
1.協調者:向所有參與者發出“Request-to-Prepare”,進入提交階段。
2.參與者:收到協調者的“Request-to-Prepare”,執行事務操作。
(1)事務執行成功,並寫入Undo log和Redo log,返回“Prepared”。
(2)事務執行失敗,返回“abort”。
提交階段:
1.協調者:有超時機制
(1)如果所有參與者應答“Prepared”,協調者向所有參與者發出“Commit”。等待所有參與者返回“Done”,結束事務。
(2)如果存在參與者應答“Abort”,協調者向所有參與者發出“Rollback”。等待所有參與者返回“Done”,結束事務。
(3)如果到達協調者的超時時間,仍未收到所有參與者的應答,則向參與者發出“Rollback”。
2.參與者:
(1)收到“Commit”,完成操作,並釋放在整個事務期間內佔用的資源和鎖,返回“Done”。
(2)收到“Rollback”,參與者利用之前寫入的Undo信息執行回滾,並釋放在整個事務期間內佔用的資源,返回“Done”。
2PC存在的問題:
1.參與者無超時機制:一旦參與者故障,可能導致事務資源一直被鎖定(同步阻塞);協調者故障,導致所有參與者一直鎖定事務資源(單點故障)。
2.數據不一致:在提交階段,部分參與者收到commit並執行commit,部分參與者因爲網絡等問題沒收到消息導致無法執行事務提交。
3.無法解決:在提交階段,協調者在發出第一個commit後宕機,唯一收到此commit消息的參與者也宕機。協調者重新選舉出來後也不知道事務應該提交還是不提交。
三階段提交(3PC)
圖片來源:https://en.wikipedia.org/wiki/Three-phase_commit_protocol
狀態扭轉
圖片來源:https://developer.jboss.org/wiki/Three-phaseCommitProtocol
CanCommit:
1.協調者:協調者向所有參與者詢問“CanCommit”,協調者變更爲waiting狀態,等待參與者應答
(1)所有參與者返回“Yes”,協調者進入PreCommit階段。
(2)有參與者返回“No”,協調者中斷事務,併發送“abort”給所有參與者,變更爲“aborted”狀態。
(3)協調者等待超時,協調者中斷事務,併發送“abort”給所有參與者,變更爲“aborted”狀態。
2.參與者:判斷是否能提交事務
(1)能提交事務,返回“Yes”,變更爲“waiting”狀態。
(2)不能提交事務,返回“No”,變更爲“abored”狀態。
(3)接受到協調者的“abort”請求,變更爲“aborted”狀態。
PreCommit(如果CanCommit階段中所有參與者都返回“Yes”)
1.協調者:發送“PrepareCommit”給所有參與者,協調者進入pre-commit狀態,等待參與者應答。
(1)所有參與者都返回“ack”,進入DoCommit階段。
(2)有參與者返回“abort”後,執行事務的中斷,協調者向所有參與者發送“abort”,變更爲“aborted”狀態。
(3)協調者等待參與者應答的時候,協調者發生超時,協調者會中斷事務,協調者向所有參與者發送“abort”,變更爲“aborted”狀態。
2.參與者:執行事務操作,並將undo和redo信息記錄到事務日誌中
(1)執行成功,返回“ack”,變更爲“pre-commit”狀態。
(2)執行失敗,返回“abort”,變更爲“aborted”狀態。
(3)等待協調者的“PrepareCommit”超時,返回“abort”,變更爲“aborted”狀態。
(4)接收到協調者的“absort”請求,中斷事務,變更爲“aborted”狀態。
DoCommit
1.協調者:如果所有參與者在PreCommit階段都返回“ack”,則發送“commit”給所有參與者,協調者進入“commited”狀態。
(1)協調者收到所有參與者的“ack”應答,事務結束。
(2)協調者等待參與者“ack”應答超時,協調者中斷事務,發送“abort”給所有參與者,進入“aborted”狀態。
2.協調者:如果有參與者返回“abort”,則發送“abort”給所有參與者,中斷事務,協調者進入“aborted”狀態。
3.參與者:根據協調者發出的命令進行操作
(1)參與者收到協調者的“commit”,執行事務提交,並釋放所有的資源和鎖,參與者進入“commited”狀態。返回“ack”。
(2)參與者收到協調者的“abort”,根據undo日誌進行回滾,並釋放所有的資源和鎖,參與者進入“aborted”狀態,返回“ack”。
(3)參與者爲“pre-commit”狀態,沒有收到協調者的“commit”或“abort”,會在等待超時後,提交事務(可能出現數據一致性的問題,例如參與者沒有收到的消息是“abort”)。
3PC存在的問題:
1.數據不一致:在DoCommit階段,如果因爲網絡問題,協調者發出的abort沒有及時被參與者接收。這時候參與者最終執行了commit,就會引發數據不一致的問題。
2.需要更多的通訊次數,實現複雜
3PC在2PC上的改動點:
- 在協調者和參與者中都引入超時機制(處理同步阻塞、單點故障問題)。
- 將2PC的“準備階段”切分成:CanCommit、DoCommit。在CanCommit階段中儘早給出事務是否可以執行的判斷,減少資源佔用,提高吞吐量。
- 在DoCommit階段,即使協調者宕機,如果參與者不是abort和commited狀態,就只能是pre-commit狀態,最終也會提交事務。因爲當該參與者是“pre-commit”狀態時,意味着所有參與者都在CanCommit階段中應答了,很大概率是可以成功執行事務的。因爲在這3個階段任意一個階段中,如果任意一個參與者故障、超時、不能執行事務,協調者都會發送abort給所有參與者中斷事務。
參考:
https://developer.jboss.org/wiki/Three-phaseCommitProtocol
https://en.wikipedia.org/wiki/Two-phase_commit_protocol
https://en.wikipedia.org/wiki/Three-phase_commit_protocol