分布式系统的一致性协议之 2PC 和 3PC
在分布式系統領域,有一個理論,對于分布式系統的設計影響非常大,那就是 CAP 理論,即對于一個分布式系統而言,它是無法同時滿足 Consistency(強一致性)、Availability(可用性) 和 Partition tolerance(分區容忍性) 這三個條件的,最多只能滿足其中兩個。但在實際中,由于網絡環境是不可信的,所以分區容忍性幾乎是必不可選的,設計者基本就是在一致性和可用性之間做選擇,當然大部分情況下,大家都會選擇犧牲一部分的一致性來保證可用性(可用性較差的系統非常影響用戶體驗的,但是對另一些場景,比如支付場景,強一致性是必須要滿足)。但是分布式系統又無法徹底放棄一致性(Consistency),如果真的放棄一致性,那么就說明這個系統中的數據根本不可信,數據也就沒有意義,那么這個系統也就沒有任何價值可言。
CAP 理論
CAP 理論三個特性的詳細含義如下:
分區容忍性
很多人可能對分區容忍性不太理解,知乎有一個回答對這個解釋的比較清楚(CAP理論中的P到底是個什么意思?),這里引用一下:
- 一個分布式系統里面,節點組成的網絡本來應該是連通的。然而可能因為一些故障,使得有些節點之間不連通了,整個網絡就分成了幾塊區域。數據就散布在了這些不連通的區域中。這就叫分區。
- 當你一個數據項只在一個節點中保存,那么分區出現后,和這個節點不連通的部分就訪問不到這個數據了。這時分區就是無法容忍的。
- 提高分區容忍性的辦法就是一個數據項復制到多個節點上,那么出現分區之后,這一數據項就可能分布到各個區里,容忍性就提高了。
- 然而,要把數據復制到多個節點,就會帶來一致性的問題,就是多個節點上面的數據可能是不一致的。
- 要保證一致,每次寫操作就都要等待全部節點寫成功,而這等待又會帶來可用性的問題。
- 總的來說就是,數據存在的節點越多,分區容忍性越高,但要復制更新的數據就越多,一致性就越難保證。為了保證一致性,更新所有節點數據所需要的時間就越長,可用性就會降低。
CAP 如何選擇
CAP 理論一個經典原理如下所示:
CAP 理論原理
CAP 定理表明,在存在網絡分區的情況下,一致性和可用性必須二選一。而在沒有發生網絡故障時,即分布式系統正常運行時,一致性和可用性是可以同時被滿足的。但是,對于大多數互聯網應用來說,因為規模比較大,部署節點分散,網絡故障是常態,可用性是必須要保證的,所以只有舍棄一致性來保證服務的 AP。但是對于一些金融相關行業,它有很多場景需要確保一致性,這種情況通常會權衡 CA 和 CP 模型,CA 模型網絡故障時完全不可用,CP 模型具備部分可用性。
在一個分布式系統中,對于這三個特性,我們只能三選二,無法同時滿足這三個特性,三選二的組合以及這樣系統的特點總結如下(來自左耳朵耗子推薦:分布式系統架構經典資料):
- CA (Consistency + Availability):關注一致性和可用性,它需要非常嚴格的全體一致的協議,比如“兩階段提交”(2PC)。CA 系統不能容忍網絡錯誤或節點錯誤,一旦出現這樣的問題,整個系統就會拒絕寫請求,因為它并不知道對面的那個結點是否掛掉了,還是只是網絡問題。唯一安全的做法就是把自己變成只讀的。
- CP (consistency + partition tolerance):關注一致性和分區容忍性。它關注的是系統里大多數人的一致性協議,比如:Paxos 算法 (Quorum 類的算法)。這樣的系統只需要保證大多數結點數據一致,而少數的結點會在沒有同步到最新版本的數據時變成不可用的狀態。這樣能夠提供一部分的可用性。
- AP (availability + partition tolerance):這樣的系統關心可用性和分區容忍性。因此,這樣的系統不能達成一致性,需要給出數據沖突,給出數據沖突就需要維護數據版本。Dynamo 就是這樣的系統。
對于分布式系統分區容忍性是天然具備的要求,否則一旦出現網絡分區,系統就拒絕所有寫入只允許可讀,這對大部分的場景是不可接收的,因此,在設計分布式系統時,更多的情況下是選舉 CP 還是 AP,要么選擇強一致性弱可用性,要么選擇高可用性容忍弱一致性。
一致性模型
關于分布式系統的一致性模型有以下幾種:
強一致性
當更新操作完成之后,任何多個后續進程或者線程的訪問都會返回最新的更新過的值,直到這個數據被其他數據更新為止。
但是這種實現對性能影響較大,因為這意味著,只要上次的操作沒有處理完,就不能讓用戶讀取數據。
弱一致性
系統并不保證進程或者線程的訪問都會返回最新更新過的值。系統在數據寫入成功之后,不承諾立即可以讀到最新寫入的值,也不會具體的承諾多久之后可以讀到。但會盡可能保證在某個時間級別(比如秒級別)之后,可以讓數據達到一致性狀態。
最終一致性
最終一致性也是弱一致性的一種,它無法保證數據更新后,所有后續的訪問都能看到最新數值,而是需要一個時間,在這個時間之后可以保證這一點,而在這個時間內,數據也許是不一致的,這個系統無法保證強一致性的時間片段被稱為「不一致窗口」。不一致窗口的時間長短取決于很多因素,比如備份數據的個數、網絡傳輸延遲速度、系統負載等。
最終一致性在實際應用中又有多種變種:
| 因果一致性 | 如果 A 進程在更新之后向 B 進程通知更新的完成,那么 B 的訪問操作將會返回更新的值。而沒有因果關系的 C 進程將會遵循最終一致性的規則(C 在不一致窗口內還是看到是舊值)。 |
| 讀你所寫一致性 | 因果一致性的特定形式。一個進程進行數據更新后,會給自己發送一條通知,該進程后續的操作都會以最新值作為基礎,而其他的進程還是只能在不一致窗口之后才能看到最新值。 |
| 會話一致性 | 讀你所寫一致性的特定形式。進程在訪問存儲系統同一個會話內,系統保證該進程可以讀取到最新之,但如果會話終止,重新連接后,如果此時還在不一致窗口內,還是可嫩讀取到舊值。 |
| 單調讀一致性 | 如果一個進程已經讀取到一個特定值,那么該進程不會讀取到該值以前的任何值。 |
| 單調寫一致性 | 系統保證對同一個進程的寫操作串行化。 |
它們的關系又如下圖所示(圖來自?《大數據日知錄:架構與算法》):
一致性模型之間關系
分布式一致性協議
為了解決分布式系統的一致性問題,在長期的研究探索過程中,業內涌現出了一大批經典的一致性協議和算法,其中比較著名的有二階段提交協議(2PC),三階段提交協議(3PC)和 Paxos 算法(本文暫時先不介紹)。
Google 2009年 在Transaction Across DataCenter?的分享中,對一致性協議在業內的實踐做了一簡單的總結,如下圖所示,這是 CAP 理論在工業界應用的實踐經驗。
CAP 理論在工業界的實踐
其中,第一行表頭代表了分布式系統中通用的一致性方案,包括冷備、Master/Slave、Master/Master、兩階段提交以及基于 Paxos 算法的解決方案,第一列表頭代表了分布式系統大家所關心的各項指標,包括一致性、事務支持程度、數據延遲、系統吞吐量、數據丟失可能性、故障自動恢復方式。
兩階段提交協議(2PC)
二階段提交協議(Two-phase Commit,即2PC)是常用的分布式事務解決方案,它可以保證在分布式事務中,要么所有參與進程都提交事務,要么都取消事務,即實現 ACID 的原子性(A)。在數據一致性中,它的含義是:要么所有副本(備份數據)同時修改某個數值,要么都不更改,以此來保證數據的強一致性。
2PC 要解決的問題可以簡單總結為:在分布式系統中,每個節點雖然可以知道自己的操作是成功還是失敗,卻是無法知道其他節點的操作狀態。當一個事務需要跨越多個節點時,為了保持事務的 ACID 特性,需要引入一個作為協調者的組件來統一掌控所有節點(參與者)的操作結果并最終指示這些節點是否要把操作結果進行真正的提交(比如將更新后的數據寫入磁盤等等)。因此,二階段提交的算法思路可以概括為: 參與者將操作結果通知協調者,再由協調者根據所有參與者的反饋情報決定各參與者是否要提交操作還是中止操作。
2PC 過程
關于兩階段提交的過程如下圖所示:
兩階段提交過程
顧名思義,2PC 分為兩個過程:
2PC 一致性問題
這里先討論一下,2PC 是否可以在任何情況下都可以解決一致性問題,在實際的網絡生產中,各種情況都有可能發生,這里,我們先從理論上分析各種意外情況。
2PC 在執行過程中可能發生 Coordinator 或者參與者突然宕機的情況,在不同時期宕機可能有不同的現象。
| Coordinator 掛了,參與者沒掛 | 這種情況其實比較好解決,只要找一個 Coordinator 的替代者。當他成為新的 Coordinator 的時候,詢問所有參與者的最后那條事務的執行情況,他就可以知道是應該做什么樣的操作了。所以,這種情況不會導致數據不一致。 |
| 參與者掛了(無法恢復),Coordinator 沒掛 | 如果掛了之后沒有恢復,那么是不會導致數據一致性問題。 |
| 參與者掛了(后來恢復),Coordinator 沒掛 | 恢復后參與者如果發現有未執行完的事務操作,直接取消,然后再詢問 Coordinator 目前我應該怎么做,協調者就會比對自己的事務執行記錄和該參與者的事務執行記錄,告訴他應該怎么做來保持數據的一致性。 |
還有一種情況是:參與者掛了,Coordinator 也掛了,需要再細分為幾種類型來討論:
| Coordinator 和參與者在第一階段掛了 | 由于這時還沒有執行 commit 操作,新選出來的 Coordinator 可以詢問各個參與者的情況,再決定是進行 commit 還是 roolback。因為還沒有 commit,所以不會導致數據一致性問題。 |
| Coordinator 和參與者在第二階段掛了,但是掛的這個參與者在掛之前還沒有做相關操作 | 這種情況下,當新的 Coordinator 被選出來之后,他同樣是詢問所有參與者的情況。只要有機器執行了 abort(roolback)操作或者第一階段返回的信息是 No 的話,那就直接執行 roolback 操作。如果沒有人執行 abort 操作,但是有機器執行了 commit 操作,那么就直接執行 commit 操作。這樣,當掛掉的參與者恢復之后,只要按照 Coordinator 的指示進行事務的 commit 還是 roolback 操作就可以了。因為掛掉的機器并沒有做 commit 或者 roolback 操作,而沒有掛掉的機器們和新的 Coordinator 又執行了同樣的操作,那么這種情況不會導致數據不一致現象。 |
| Coordinator 和參與者在第二階段掛了,掛的這個參與者在掛之前已經執行了操作。但是由于他掛了,沒有人知道他執行了什么操作。 | 這種情況下,新的 Coordinator 被選出來之后,如果他想負起 Coordinator 的責任的話他就只能按照之前那種情況來執行 commit 或者 roolback 操作。這樣新的 Coordinator 和所有沒掛掉的參與者就保持了數據的一致性,我們假定他們執行了 commit。但是,這個時候,那個掛掉的參與者恢復了怎么辦,因為他已經執行完了之前的事務,如果他執行的是 commit 那還好,和其他的機器保持一致了,萬一他執行的是 roolback 操作呢?這不就導致數據的不一致性了么?雖然這個時候可以再通過手段讓他和 Coordinator 通信,再想辦法把數據搞成一致的,但是,這段時間內他的數據狀態已經是不一致的了! |
所以,2PC協議中,如果出現協調者和參與者都掛了的情況,有可能導致數據不一致。為了解決這個問題,衍生除了3PC。
2PC 優缺點
簡單總結一下 2PC 的優缺點:
- 優點:原理簡潔清晰、實現方便;
- 缺點:同步阻塞、單點問題、某些情況可能導致數據不一致。
關于這幾個缺點,在實際應用中,都是對2PC 做了相應的改造:
三階段提交協議(3PC)
三階段提交協議(Three-Phase Commit, 3PC)最關鍵要解決的就是 Coordinator 和參與者同時掛掉導致數據不一致的問題,所以 3PC 把在 2PC 中又添加一個階段,這樣三階段提交就有:CanCommit、PreCommit 和 DoCommit 三個階段。
3PC 過程
三階段提交協議的過程如下圖(圖來自?維基百科:三階段提交)所示:
三節點提交過程
3PC 的詳細過程如下(這個過程步驟內容來自?2PC到3PC到Paxos到Raft到ISR):
階段一 CanCommit
階段二 PreCommit
執行事務預提交:如果 Coordinator 接收到各參與者反饋都是Yes,那么執行事務預提交:
中斷事務:如果任何一個參與者向 Coordinator 反饋了 No 響應,或者在等待超時后,Coordinator 無法接收到所有參與者的反饋,那么就會中斷事務。
階段三 doCommit
執行提交
中斷事務:假設 Coordinator 正常工作,并且有任一參與者反饋 No,或者在等待超時后無法接收所有參與者的反饋,都會中斷事務
3PC 分析
3PC 雖然解決了 Coordinator 與參與者都異常情況下導致數據不一致的問題,3PC 依然帶來其他問題:比如,網絡分區問題,在 preCommit 消息發送后突然兩個機房斷開,這時候 Coordinator 所在機房會 abort, 另外剩余參與者的機房則會 commit。
而且由于3PC 的設計過于復雜,在解決2PC 問題的同時也引入了新的問題,所以在實際上應用不是很廣泛。
參考:
- 維基百科:二階段提交;
- 維基百科:三階段提交;
- 左耳朵耗子推薦:分布式系統架構經典資料;
- 關于分布式一致性的探究;
- 關于分布式事務、兩階段提交協議、三階提交協議;
- 深入理解分布式系統的2PC和3PC;
- 2PC到3PC到Paxos到Raft到ISR;
- 《大數據日知錄:架構與算法》;
- 分布式系統的事務處理。
總結
以上是生活随笔為你收集整理的分布式系统的一致性协议之 2PC 和 3PC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解析微服务架构与最佳实践
- 下一篇: 复胃散片_功效作用注意事项用药禁忌用法用