天天看點

分布式事務2PC和3PC

分布式中的事務

在單服務的時候運作業務的時候,進行事務管理通常是比較簡單的。但是在分布式環境下,事務被分散到各個執行個體中,每次執行事務都需要保證各個系統的事務完成。但是受限于不同執行個體伺服器的穩定性,網絡的可靠性,完成一項事務會變得非常麻煩。

CAP理論

說道分布式事務是繞不開CAP理論。所謂的CAP指的是一緻性(Consistency),可用性(Availability),分區容忍性(Partition tolerance)。

一緻性(Consistency)

每次讀取要麼是最新的資料,要麼是一個錯誤

可用性(Availability)

用戶端在任何時刻的讀寫操作都能在限定的延遲内完成的,即每次請求都能獲得一個響應,但不保證是最新的資料;

分區容忍性(Partition tolerance)

分布式系統中,節點組成的網絡都是連通的。但是可能存在一些文檔,導緻連通的節點中斷聯系了。整個連通的網絡成了分散的幾塊區域。資料被分割在不同的區域裡面。這個時候任何一個事務都無法擷取完整的資料。這時分區就是無法容忍的。在大規模分布式系統中,網絡分區現象是必然會發生的,系統應該能保證在這種情況下可以正常工作。

對CAP的滿足

實際上發現很難去完全實作CAP的所有要求。我們一般隻能實作兩項。或者實作一項,均衡的實作其他兩項内容。

CA (Consistency + Availability)

關注一緻性和可用性。這種它需要非常嚴格的全體一緻的協定。CA 系統不能容忍網絡錯誤或節點錯誤,一旦出現這樣的問題,整個系統就會拒絕寫請求,因為它并不知道對面的那個結點是否挂掉了。常用的就是2PC。。

CP (consistency + partition tolerance)

關注一緻性和分區容忍性,它關注的是系統裡大多數人的一緻性協定,這樣的系統隻需要保證大多數結點資料一緻,而少數的結點會在沒有同步到最新版本的資料時變成不可用的狀态。比如:Paxos 算法。

AP (availability + partition tolerance)

關心可用性和分區容忍性。是以,這樣的系統不能達成一緻性,需要給出資料沖突,給出資料沖突就需要維護資料版本。Dynamo 就是這樣的系統。

根據CAP的理論,我們要麼實作AP,要麼CP,要麼AC。假如一個分布式系統中不存在副本,則資料一定是強一緻的,不可能發現資料不一緻。但是此時發生了資料分區系統則一定會拒絕通路的。但是我們提供備份避免服務分區,則在大規模分布式中一定會存在資料不一緻的情況。這個時候可用性和一緻性發生了沖突。我們需要在強一緻性弱可用性和高可用性容忍弱一緻性做出選擇。為了解決分布式系統的一緻性問題,常出現了二階段送出協定(2PC),三階段送出協定(3PC)這些解決方案

2PC

2PC:Two-phase Commit,二階段送出協定。是一種比較常用的分布式事務解決方案。其主要的作用是在分布式事務中,要麼所有參與者都送出事務,要麼都取消事務,保證參與者的一緻性。

二階段送出

2PC将事務的送出分成了兩個過程:1. 準備階段 2. 送出階段

準備階段

  1. 在準備階段,協調者向所有參與者發送一個vote request确認參與者準備好開始事務。
  2. 參與者在收到請求後,各參與者節點準備事務操作。如果準備好則傳回一個“同意”辨別,如果沒有準備好則傳回一個“中止”辨別。

送出階段

  1. 協調者收到所有參與者的回報後,如果所有參與者認為可以送出,則送出事務,否則就中斷事務。并将處理結果發送給參與者。
  2. 作為參與者,如果收到送出消息則送出本地事務,否則取消本地事務。

此時事務可以送出

2PC存在的問題

既然是分布式事務,在分布式環境下我們不得不考慮一些特殊情況下出現不同的錯誤要如何解決

同步阻塞

整個事務過程中,所有參與者都處于阻塞狀态

協調者當機

協調者是整個事務的核心,當協調者當機,參與者會被鎖定

未完全執行事務

在第二階段如果協調者和參與者都當機,即使後續都回複了,假如此時參與者已經執行了事務操作,但是這時候無論協調者還是他自己都無法知道。協調者備份會将執行事務的指令再次發送給參與者,會産生錯誤資料。

在實際中也嘗試對上面的問題進行修複:針對協調者當機,提供了協調者備份。當協調者當機後,備份會啟動接替協調者的職責。但是對于第二階段部分參與者或者參與者和協調者都當機後存在資料不一緻,以及同步阻塞的問題還是無法解決。

3PC

為了解決2PC在資料不一緻上出現的問題,于是提出了2PC的更新版3PC。

在3PC中事務被分為了三個階段:CanCommit、PreCommit、doCommit。整個階段使用維基百科可以描述為下面内容

三階段送出

CanCommit階段(送出詢問)

  1. 協調者想各個參與者詢問是否可以進行事務送出,并收集響應結果
  2. 參與者向協調者回報事務内容。此時收集到的回報為同意則進入預備階段,否則中斷事務

PreCommit階段(預送出)

  1. 事務預送出,如果詢問事務的傳回都是同意,協調者則向各個參與者發送預送出請求,并進入prepared 階段
  2. 參與者接收到預送出請求後,執行事務操作,并儲存Undo 和 Redo 資訊記錄到事務日記中
  3. 各個參與者向協調者回報事務執行的響應,如果完成事務操作,則回報給協調者。同時等待最終指令,執行送出或者終止
  4. 如果協調者收到預送出的響應為拒絕或者逾時,則執行中斷事務操作,向各個參與者回報事務執行響應。
  5. 參與者收到中斷事務的響應,或者等待逾時,都會主動中斷事務。

doCommit階段(最終送出)

  1. 協調者收到各個參與者響應,則從預送出進入送出階段,并向參與者發送送出請求
  2. 參與者收到送出指令,正式送出事務
  3. 參與者向伺服器回報最終送出結果
  4. 協調者收到所有回報資訊,完成事務
  5. 此時假如有協調者沒有收到回報,則發送中斷事務指令
  6. 參與者收到拒絕指令後,利用日志開始進行事務復原。
  7. 參與者回報復原結果
  8. 參與者接收回報,中斷事務

上面内容可以用下面的來表示

和2PC相比,3PC對于協調者和參與者都設定了逾時時間,這樣避免了參與者在長時間無法和協調者通訊的時候,無法釋放資源。因為參與者自身擁有逾時機制會在逾時後,自動進行中斷進而進行釋放資源。

通過CanCommit、PreCommit、DoCommit三個階段的設計,相較于2PC而言,多設定了一個緩沖階段保證了在最後送出階段之前各參與節點的狀态是一緻的。當然3PC也隻是多了一個階段的保護,也并沒有完全解決資料不一緻的問題。

比較疑惑的地方

有一些問題感覺描述的很混亂。根據wiki上的圖以及描述

If, after a cohort member receives a preCommit message, the coordinator fails or times out, the cohort member goes forward with the commit.
分布式事務2PC和3PC

預送出逾時的時候會進行送出操作,但是網上很多部落格的說法卻是

PreCommit階段:無論收到協調者發出的abort請求,或者在等待協調者請求過程中出現逾時,參與者均會中斷事務。

這裡表述有點模糊,按照wiki說法在預送出後沒有收到最終确認則參與者直接送出。但是國内很多部落格上描述是等待協調者請求過程中出現逾時則直接中斷事務,我這裡我看了國内很多人總結2PC和3PC中的一句話

協調者發送的abort響應沒有及時被參與者接收到,那麼參與者在等待逾時之後執行了commit操作

,是以我認為在預送出沒有獲得協調者回報的情況下應該是直接送出的。但這是個我個人的想法,是以我這裡标注了存疑。希望有了解的朋友解答下。

繼續閱讀