一.寫在前面
分布式系統(tǒng)一致性專題本期該寫 3PC 協(xié)議了,上周太忙沒有時間更新,就拿了之前的舊文章做了一些調(diào)整重發(fā)了一下,還望各位讀者海涵。
后面大約還有3期:Paxos 協(xié)議、Raft 協(xié)議等,先預(yù)熱一下。 溫馨提示:本篇文章并不會枯燥,換了個畫圖工具,對于我這種建筑專業(yè)出身的IT狗來說,畫圖簡直是最開心的事情了,所以放心看吧!二.3PC的出現(xiàn)
之前文章中提到了 2PC 協(xié)議存在的 協(xié)調(diào)者單點、參與者阻塞超時、網(wǎng)絡(luò)分區(qū)、容錯性等問題,這些在某些程度上是做優(yōu)化和調(diào)整的,并不是致命問題。
我們對 2PC 協(xié)議的異常情況做了拆解,但是那是個m*n的組合問題,我們盡量去分析主要矛盾,于是發(fā)現(xiàn)在 協(xié)調(diào)者和唯一接收指令的參與者都出現(xiàn)不可恢復(fù)宕機時,即使后面選舉了新的協(xié)調(diào)者,仍然可能出現(xiàn)數(shù)據(jù)的不一致性。
3PC 的出現(xiàn)可能是多種因素促成的。
但是基本上 可以確定 3PC 將對 2PC 存在的問題進行修正和優(yōu)化,但是這樣并不意味著 3PC 不會引入新的問題。
本文將從 3PC 的協(xié)議過程來闡述這兩大塊內(nèi)容。三. 3PC協(xié)議的基本過程
3PC協(xié)議 Three-Phase-Commit 又稱三階段提交協(xié)議,相比 2PC 協(xié)議增加了一個階段,因此我們普遍把 3PC 協(xié)議看作是 2PC 協(xié)議的改進版本。
3PC 協(xié)議將 2PC 協(xié)議的準備階段一分為二,從而形成了三個階段。 協(xié)調(diào)者和參與者等待超時情況單獨說,先看正常情況的基本過程,要不然容易混淆。
3.1 CanCommit階段
在2PC準備階段中,協(xié)調(diào)者向參與者發(fā)送指令后,參與者如果具備執(zhí)行條件,則獲取鎖并執(zhí)行動作,只不過未真正提交,可以認為 參與者就差臨門一腳了,還得等協(xié)調(diào)者信號。
如果是 commit 信號那還好,如果是 rollback 信號,那么對于一些本地執(zhí)行了動作的參與者來說白白浪費了,所以從這個角度來說,2PC 有點激進了,但是這么做也是有原因的,在復(fù)雜的網(wǎng)絡(luò)環(huán)境中多一輪交互意味著性能的損耗。
3PC來說更加合理,先由協(xié)調(diào)者向參與者發(fā)送詢問信號, 兄弟們有檔期嗎??然后開始收集反饋,相比來說 更加輕量。
這個階段參與者并不真實獲取鎖占用資源,只是對自身執(zhí)行事務(wù)狀態(tài)的檢查,查看是否具備執(zhí)行事務(wù)的條件,進而回復(fù) 詢問。
根據(jù)參與者對詢問的反饋,在 CanCommit 階段可能出現(xiàn)的兩情況: A.所有參與者均Ready的場景
B.存在參與者不OK的場景3.2 PreCommit階段
第二個階段的具體動作取決于第一個階段的結(jié)果,因此可以分為兩種情況:
3.3 DoCommit階段
這是 3PC 的第三個階段和2PC的第二個階段類似,同樣的 DoCommit 執(zhí)行具體動作取決于第二階段 PreCommit 的結(jié)果,因此仍然分為兩種情況:
四. 3PC中的超時策略
我們前面提到 3PC 要解決 2PC 的參與者阻塞超時問題,在2PC中參與者比較癡情,協(xié)調(diào)者不給信號會長時間阻塞,不釋放資源,這樣別人也沒法處理其他事情,確實不太好,看來 2PC 還是太依賴協(xié)調(diào)者了。
3PC 認為網(wǎng)絡(luò)超時是普遍發(fā)生的情況,如果參與者在一種大概率確定的狀態(tài)下執(zhí)行一些動作也是被允許的,將在外軍令有所不受。
3PC 的超時處理可能發(fā)生在 PreCommit 和 DoCommit 階段:
-
參與者等待 PreCommit 超時
協(xié)調(diào)者和參與者之間可能存在較大的網(wǎng)絡(luò)延時,或者協(xié)調(diào)者出現(xiàn)故障,或者出現(xiàn)網(wǎng)絡(luò)分區(qū)等情況,參與者并不會傻等,在超過設(shè)定時間之后,參與者就繼續(xù)做之前的事情了,因為好像被大哥鴿了,只能該干啥干啥,這也是正確的決策。
-
參與者等待 DoCommit 超時
在 CanCommit 和 PreCommit 之后,參與者認為大家都對齊了都是棒棒的,如果參與者在設(shè)定時間內(nèi)并沒有收到協(xié)調(diào)者的 DoCommit 指令,那么就本地執(zhí)行提交完成這次事務(wù),因為參與者揣測大哥的意思大概率也是讓我們提交,干等著也不是辦法,回滾可能和大家不一樣,抉擇之下參與者選擇提交事務(wù)。
-
協(xié)調(diào)者等待反饋超時
3PC協(xié)調(diào)者的等待超時處理和2PC基本上是一樣的,無論在哪個階段超時都認為不具備條件,進行 abort 或者 rollback 操作,這個非常好理解。
可以看到3PC協(xié)議中參與者不再過度依賴協(xié)調(diào)者的指令信號,而是有了自己的相對獨立性,可以根據(jù)當前所處的狀態(tài)來進行自我決策。
避免了2PC中的阻塞等待帶來的資源浪費情況,確實是個不錯的優(yōu)化,但是我們并不能完全保證這種優(yōu)化就都是完全正確的呀!
換句話說3PC解決了2PC的bug,但是不代表3PC沒有引入新的bug。
五. 3PC協(xié)議的一些分析
前面我們說到3PC協(xié)議的一個重要作用就是要對2PC協(xié)議的改進和優(yōu)化,從上面的過程分析可知確實做了一些優(yōu)化,但是仍然不可避免出現(xiàn)了新的問題。5.1 3PC的數(shù)據(jù)不一致問題
2PC協(xié)議在某些場景下數(shù)據(jù)不一致問題,那么3PC有沒有這種問題呢? 答案是有,根源是新加的參與者超時機制。
比如參與者A因為自身網(wǎng)絡(luò)問題,在設(shè)定時間內(nèi)未收到協(xié)調(diào)者的信號,這時參與者A基于之前的狀態(tài)執(zhí)行了Commit操作,提交了事務(wù),這種情況確實會發(fā)生,根據(jù)真實的協(xié)調(diào)者信號是commit還是rollback會出現(xiàn)不同的結(jié)果。
如果協(xié)調(diào)者發(fā)送的是Commit指令,就和參與者A獨自決策結(jié)果一致,沒啥問題。 如果協(xié)調(diào)者在DoCommit階段發(fā)送的是rollback指令,那么超時的參與者A由于執(zhí)行了本地事務(wù)提交,從而和其他收到指令執(zhí)行rollback的參與者的數(shù)據(jù)不一致。5.2 決策狀態(tài)的對齊
我們知道 2PC協(xié)議的 決策結(jié)果初始階段只有決策者知道,只有在它發(fā)送了決策解決才有參與者知道,這樣就存在決策結(jié)果丟失的情況。
假如協(xié)調(diào)者掛掉,新協(xié)調(diào)者可以咨詢所有的參與者來確定決策狀態(tài),根據(jù)所有參與者的情況來確定,但是萬一真理掌握在少數(shù)人手中呢? 極端情況:
假如有10個參與者,9個都是正常的,1個狀態(tài)未知(先叫做A吧),10個參與者都向協(xié)調(diào)者發(fā)送了反饋,如果A反饋的是Not Ready信號,其他9個都是Ready信號。
協(xié)調(diào)者匯總結(jié)果決策出不具備執(zhí)行條件,開始向所有參與者發(fā)送rollback,恰好第一個收到信號的是A機器,協(xié)調(diào)者掛了,A收到信號后也掛了。
新的協(xié)調(diào)者詢問了其余9個都是OK,新的協(xié)調(diào)者就認為具備條件了從而發(fā)送Commit信號,這樣就出現(xiàn)了不一致。 腦洞大開:
這個過程和清宮劇中皇帝立儲很像嘛,皇帝把結(jié)果掛在朝堂的牌匾之上,假定詔書消失了且皇帝掛了,那么結(jié)果就不得而知了,智囊團在沒有私心的前提下就需要考察所有的侯選人的情況來確定,這樣就可能出現(xiàn)不一致。 決策透明化:
在3PC中仍然存在只有1臺機器收到指令然后掛掉的情況,但是如果出現(xiàn)在前置階段,對整個結(jié)果是沒有影響的,因為會被取消并且參與者并沒有本地執(zhí)行。
現(xiàn)在看3PC的思想是把做重大動作時的決策結(jié)果透明化統(tǒng)一化,產(chǎn)生的影響也就非常小了,因此PreCommit階段的狀態(tài)是明確的。
我們需要把決策結(jié)果透明化,讓所有參與者都知道決策結(jié)果,3PC的PreCommit階段對齊了結(jié)果,只要有1臺還活著,整個事務(wù)的狀態(tài)就是確定的,畢竟所有參與者全掛的情況概率非常低。六.小結(jié)
3PC協(xié)議是對2PC協(xié)議的優(yōu)化和改進,通過將2PC的準備階段一分為二:CanCommit和PreCommit, 整個過程中下一階段的流轉(zhuǎn)要取決于上一個階段的結(jié)果。
經(jīng)過CanCommit和PreCommit階段后,參與者之間對齊并保留了決策結(jié)果,避免2PC協(xié)議極端情況決策結(jié)果的錯誤缺失,是個比較好的做法。
2PC協(xié)議只有協(xié)調(diào)者有超時機制,3PC協(xié)議對參與者也引入了超時機制,在不同的階段進行不同的超時處理,但是 由于網(wǎng)絡(luò)波動和網(wǎng)絡(luò)分區(qū)存在讓參與者的超時處理帶來新的不確定性,甚至可能出現(xiàn)數(shù)據(jù)不一致。
3PC協(xié)議增加一輪詢問階段所以整個交互過程比2PC更長了,性能相比2PC是會有一些下降的,但是3PC協(xié)議對于網(wǎng)絡(luò)分區(qū)等情況也并沒有處理地很好。
總體來說, 3PC相比2PC做了很多改進有一定的效果,但是仍然存在數(shù)據(jù)不一致問題,還需繼續(xù)努力。
特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:
長按訂閱更多精彩▼
如有收獲,點個在看,誠摯感謝
免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!