1. 程式人生 > >分散式一致性演算法2PC和3PC

分散式一致性演算法2PC和3PC

 

 

  為了解決分散式一致性問題,產生了不少經典的分散式一致性演算法,本文將介紹其中的2PC和3PC。2PC即Two-Phase Commit,譯為二階段提交協議。3PC即Three-Phase Commit,譯為三階段提交協議。

 

分散式系統和分散式一致性問題

  分散式系統,即執行在多臺不同的網路計算機上的軟硬體系統,並且僅通過訊息傳遞來進行通訊和協調。
  分散式一致性問題,即相互獨立的節點之間如何就一項決議達成一致的問題。

 

2PC

  2PC,二階段提交協議,即將事務的提交過程分為兩個階段來進行處理:準備階段 和 提交階段

事務的發起者稱協調者, 事務的執行者稱參與者
 
  階段1:準備階段

  1、協調者向所有參與者傳送事務內容詢問是否可以提交事務並等待所有參與者答覆
  2、各參與者, 先鎖住資源,然後執行事務操作將Undo和Redo資訊記入事務日誌中(但不提交事務)。// 就是說 執行sql, 但是不執行 commit 
  3、如參與者執行成功,給協調者反饋YES,即可以提交;如執行失敗 ,給協調者反饋NO (或反饋超時) ,即不可提交。
 
  階段2:提交階段
  此階段分兩種情況:所有參與者均反饋YES、或任何一個參與者反饋NO。
  所有參與者均反饋YES時,即提交事務。


  任何一個參與者反饋NO時,即中斷事務。
 
  提交事務:(所有參與者均反饋YES)
  1、協調者向所有參與者發出正式提交事務的請求(即Commit請求)。// 就是發通知說 準備執行 commit 吧
  2、參與者執行Commit請求,並釋放整個事務期間佔用的資源。// 就是正式的 執行 commit , 提交之後要釋放 資源, 因為鎖已經釋放。
  3、各參與者向協調者反饋Ack完成的訊息。 // ack 也是不能不忘記的
  4、協調者收到所有參與者反饋的Ack訊息後,即完成事務提交。

 

  中斷事務:(任何一個參與者反饋NO)
  1、協調者向所有參與者發出回滾請求(即Rollback請求)。
  2、參與者使用階段1中的Undo資訊執行回滾操作,並釋放整個事務期間佔用的資源。// 就是正式的 執行 rollback,回滾 之後也會 釋放 資源, 因為鎖已經釋放。


  3、各參與者向協調者反饋Ack完成的訊息。
  4、協調者收到所有參與者反饋的Ack訊息後,即完成事務中斷。

 

 

小結:

2pc中,參與者沒有超時機制, 所以, 如果協調者沒有或 沒有正確 發生指令過來, 那麼 會 一直佔用資源。

協調者會等待 參與者的響應, —— 這是2pc 中 唯一的一個超時 時間

提交事務或  中斷 事務 的時候, 協調者 都需要 等待 所有 參與者的 ack,  這個過程可能 參與者、協調者、網路 發生故障,如果 協調者正常且 只收到 部分 ack, 怎麼辦? 事務是否要 繼續 完成? 還是記為 待 完成狀態?  比較鬱悶的是,找了很多的 部落格, 沒有看到 對這個問題有進行說明的。。   我感覺是 先會記錄為待 完成, 然後 要麼協調者 停止工作; 要麼 發出 error 警告後 繼續工作。

 

2PC的缺陷

  1、同步阻塞:最大的問題即同步阻塞,即:所有參與事務的邏輯均處於阻塞狀態。
  2、單點:協調者存在單點問題,如果協調者出現故障,參與者將一直處於鎖定狀態。
  3、腦裂:在階段2中,如果只有部分參與者接收並執行了Commit請求,會導致節點資料不一致。// 就是“提交事務”的時候, 協調者只有收到部分的ack.
 
  由於2PC存在如上同步阻塞、單點、腦裂問題,因此又出現了2PC的改進方案,即3PC。
 

3PC

 

  3PC,三階段提交協議,是2PC的改進版本,即將事務的提交過程分為CanCommit、PreCommit、do Commit三個階段來進行處理。
 
  階段1:CanCommit
  1、協調者向所有參與者 發出包含事務內容的CanCommit請求,詢問是否可以提交事務,並等待所有參與者答覆。—— 這裡的 等待 肯定有 超時機制
  2、參與者收到CanCommit請求後,如果認為可以執行事務操作,則反饋YES並進入預備狀態(某個參與者進入預備狀態之後, 它會等待 協調者的響應, 這裡也有超時機制, 如果超時了, 那麼直接 abort ! ),否則反饋NO。 —— 參與者 需要負責 檢測資源是否足夠, 然後 “預留” 資源。 但是, 這一步驟, 參與者 不會鎖住資源。。 預留 不是鎖。

 

  階段2:PreCommit
  此階段分兩種情況:
  1、所有參與者均反饋YES,即執行事務預提交。
  2、任何一個參與者反饋NO,或者等待超時後協調者尚無法收到所有參與者的反饋,即中斷事務。
 
  事務預提交:(所有參與者均反饋YES時)
  1、協調者向所有參與者發出PreCommit請求,進入準備階段。
  2、參與者收到PreCommit請求後,執行事務操作,將Undo和Redo資訊記入事務日誌中(但不提交事務)。—— 鎖住資源, 執行事務, 參與者向協調者反饋Ack響應或No響應,並等待最終指令。然後 進入 等待狀態, 超時後就直接提交, 為什麼呢? 因為進入了 這一步驟, 那麼一定是 CanCommit 階段所有的參與者都是返回yes—— 如果這個時候 協調者又傳送了 abort 命令呢? 。
   
 
  中斷事務:(任何一個參與者反饋NO,或者等待超時後協調者尚無法收到所有參與者的反饋時)
  1、協調者向所有參與者發出 abort 請求。
  2、無論收到協調者發出的abort請求,或者在等待協調者請求過程中出現超時,參與者均會中斷事務。
 
  階段3:do Commit
  此階段也存在兩種情況:
  1、所有參與者均反饋Ack響應,即執行真正的事務提交。
  2、任何一個參與者反饋NO,或者等待超時後協調者尚無法收到所有參與者的反饋,即中斷事務。
 
  提交事務:(所有參與者均反饋Ack響應時)
  1、如果協調者處於工作狀態,則向所有參與者發出do Commit請求。
  2、參與者收到do Commit請求後,會正式執行事務提交,並釋放整個事務期間佔用的資源。並且, 各參與者向協調者反饋Ack完成的訊息。
  3、協調者收到所有參與者反饋的Ack訊息後,即完成事務提交。(  無論如何, 都得完成 這個事務 )
 
  中斷事務:(任何一個參與者反饋NO,或者等待超時後協調者尚無法收到所有參與者的反饋時)
  1、如果協調者處於工作狀態,向所有參與者發出abort請求。 //  如果 協調者處於非工作狀態, ??
  2、參與者使用階段1中的Undo資訊執行回滾操作,並釋放整個事務期間佔用的資源。並且, 各參與者向協調者反饋Ack完成的訊息。
  3、協調者收到所有參與者反饋的Ack訊息後,即完成事務中斷。 
 
  注意:進入階段三後,無論協調者出現問題,或者協調者與參與者網路出現問題,都會導致參與者無法接收到協調者發出的do Commit請求或abort請求。此時,參與者都會在等待超時之後,繼續執行事務提交。

 

3PC的優點和缺陷

  優點:降低了阻塞範圍,在等待超時後協調者或參與者會中斷事務。避免了協調者單點問題,階段3中協調者出現問題時,參與者會繼續提交事務。 ??? 
 
  缺陷:腦裂問題依然存在,即在參與者收到PreCommit請求後等待最終指令,如果此時協調者無法與參與者正常通訊,會導致參與者繼續提交事務,造成資料不一致。
 

後記

  無論2PC或3PC,均無法徹底解決分散式一致性問題。
  解決一致性問題,唯有Paxos,後續將單獨總結。

  3pc 其實 相對於 2pc 就是多了一個CanConmmit 階段, 這個階段的作用呢? 我想 就是 保證各個 參與者與 協調者 的網路是ok 的,避免 “參與者 立即 執行事務操作” !

       但是不管是2PC還是3PC都存在資料一致性的問題:
2PC:比如協調者在只給部分參與者傳送了Commit請求,那就會出現部分參與者執行了Commit,部分沒有提交 ( 會一直阻塞 等待!),出現不一致問題。
3PC:在第三階段,一旦參與者無法及時收到來自協調者的資訊之後,他會預設執行commit。而不會一直持有事務資源並處於阻塞狀態,但是這種機制也會導致資料一致性問題—— 萬一 協調者需要的是 abort 呢? 因為 可能協調者 執行延遲傳送資料而已。。

 

還有想要說的是, 2pc 或 3pc 也好, 有沒有明確的限定 階段 的操作?  我認為是有的, 首先要區分是協調者還是參與者, 然後再看具體情況: 

對於 2pc:

協調者一開始處於準備階段, 傳送事務及 詢問 後, 然後等待反饋。 但參與者還沒有,協調者雖然傳送出去了, 但是參與者還沒有立即收到, 有一定的網路延遲。 參與者收到了之後, 參與者就算正式進入了 準備階段。  然後參與者 進行sql操作(並不提交),然後 反饋Yes 或者 No。 這個時候, 反饋已經完畢, 參與者就算了 準備完成了。

參與者等待反饋超時,進入中斷流程,完了準備階段 結束, 但是沒有進入提交階段。

 

然後,協調者收到了各個參與者的反饋, 然後,

如果有一個是No,然後進入中斷流程,完了準備階段 結束, 但是沒有進入提交階段。

如果都是Yes,然後協調者就算是進入了提交階段,協調者向各個參與者傳送Commit命令,完了就等待響應。

 

參與者並不知道 協調者會發送什麼命令過來, 會一直 一直等待。 如果收到了Commit命令,那麼就算是進入了提交階段, 然後正式的 commit, 然後反饋ack(Y 還是N ?這個時候 有可能反饋N 嗎?), 然後完成 提交階段。這個時候參與者是完成了提交階段, 但是協調者還沒有。

協調者如果收到了所有的node 反饋ack, 那麼就結束 提交階段。 (如果不呢?)

注意,各個階段直接是沒有 其他多餘的操作的, 也就是沒有其他階段了!

 

簡單說 2pc是這樣的,其一,協調者在第一次傳送之後 進入階段一,要麼超時時間內收到反饋, 然後處理,然後結束第一階段; 要麼超時後處理,然後結束第一階段。 發生在這個階段內的 中斷處理也算是 第一階段的內容。   其二, 協調者在第二次傳送之 後進入階段二,只有一個選擇,全部提交,然後收集所有反饋, 沒有超時機制(原因待查)。

簡單說 3pc是這樣的, 它有4個超時時間, 第一階段,協調者等待 參與者(記為T1),參與者響應後等待協調者(記為T2),第二階段,協調者等待 參與者(記為T3),參與者響應後等待協調者(記為T4),出現其中任何的一個,那麼中斷。

 

90% 轉載: 

http://blog.51cto.com/11821908/2058651

https://www.cnblogs.com/shangxiaofei/p/5196260.html