漫话:如何给女朋友解释什么是2PC(二阶段提交)?
周末晚上,正在家里面看綜藝節目,突然女朋友跑過來找我打《王者榮耀》。
打了幾把游戲,終于可以歇息一會了,準備繼續看我的綜藝,可是女朋友過來找我給他講講到底什么是二階段提交。
分布式一致性
還好我們之前專門給女朋友介紹過什么是分布式,要不然這個話題說來就話長了。
在之前介紹分布式的時候,我們以飯店的后廚為例,今天繼續之前的例子來說說什么是分布式一致性。
隨著飯店的發展,慢慢的從只有一個廚師演變成有多個廚師,進而演變成有洗菜工、配菜師、廚師等多個職位。
當有了多種分工之后,就勢必需要協調這些人之間的合作。
比如餐廳客人點了一份番茄炒蛋,然后后廚開始準備起來,洗菜工開始洗西紅柿,配菜師開始準備雞蛋,廚師開始向鍋內加油準備炒菜。這是一種很正常的情況。
但是,如果消息傳達的不到位,或者洗菜師傅臨時不在廚房等,就會導致有的人已經開始準備起來,但是有的人并沒有準備。
這就像是一個分布式系統一樣的,當我們在電商網站下單的時候,需要有多個分布式服務同時服務,如支付系統進行支付、紅包系統進行紅包扣減、庫存系統扣減庫存、物流系統更新物流信息等。
但是,如果其中某一個系統在執行過程中失敗了,或者由于網絡原因沒有收到請求,那么,整個系統可能就有不一致的現象了,即:付了錢,扣了紅包,但是庫存沒有扣減。
這就是所謂的分布式系統的數據一致性問題。
二階段提交
之所以剛剛的例子中會出現一致性問題,就是因為每一個員工都只關注自己所做的事情,無法關注到其他人,那么,要想保證整體的一致性,就需要在后廚中引入一個新的角色,負責統籌,這個角色來進行協調和調配所有人。
那么,引入一個協調者負責協調所有參與者的工作,這個在分布式系統中其實就是X/Open組織定義的分布式事務處理模型,而二階段提交就是根據這一模型衍生出來的。
舉個例子,五個人相約打王者榮耀,想要一起玩需要以下幾個步驟:
有一個人想要五黑玩王者榮耀,于是他開始聯系自己的小伙伴們。
組織者:小A,我們準備玩王者榮耀,你要是可以來參加的話,現在你就登錄游戲,然后在游戲好友上給我回復個消息。
小A登錄自己的游戲賬號,然后告訴組織者:小A已就位。
組織者:小B、小C、小D,我們準備玩王者榮耀,你要是可以來參加的話,現在你就登錄游戲,然后在游戲好友上給我回復個消息。
小B、小C、小D分別登錄自己的游戲賬號,然后告訴組織者:小B、小C、小D已就位。
組織者發現所有人都就位了,于是在游戲上逐一通知大家,
組織者:小A,我邀請你了,你進來吧。
小A接受邀請
組織者:小B、小C、小D,我邀請你了,你進來吧。
小小B、小C、小D接收邀請
于是,5個人在王者峽谷愉快的玩耍了起來。
對于五個人開黑這個事務操作,在開始準備前五個人都是空閑狀態,忙著自己的事情。在組織者協調過之后,大家也要達成一個一致的狀態,即以下兩種情況之一:
1、五個人愉快的開始一起玩游戲
2、五個人都退出游戲,還是去忙自己的事情。
如果最后有一部分人在游戲里一直等,另外一部分并沒有進入游戲,那么就是數據不一致了。
以上過程,就是一個典型的二階段提交(2PC)的過程,在分布式系統中,也有同樣的問題,并且可以采用同樣的解決辦法。
在分布式系統中,每個節點雖然可以知曉自己的操作時成功或者失敗,卻無法知道其他節點的操作的成功或失敗(只知道自己有時間可以玩王者榮耀,不知道其他人有沒有)。
當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的組件來統一掌控所有參與者的操作結果并最終指示這些節點是否要把操作結果進行真正的提交(組織者通知各位參與者一起進入游戲房間)。
因此,二階段提交的算法思路可以概括為:參與者將操作成敗通知協調者,再由協調者根據所有參與者的反饋情報決定各參與者是否要提交操作還是中止操作。
所謂的兩個階段是指:第一階段:準備階段(投票階段)和第二階段:提交階段(執行階段)
準備階段
事務協調者給每個參與者發送Prepare消息,每個參與者要么直接返回失敗(告知組織者自己沒時間,不能一起玩游戲),要么在本地執行事務(登錄王者榮耀),但不提交(先不開始游戲)。
可以進一步將準備階段分為以下三個步驟:
1)協調者節點向所有參與者節點詢問是否可以執行提交操作,并開始等待各參與者節點的響應。(詢問是否可以一起玩游戲)
2)參與者節點執行詢問發起為止的所有事務操作,并將Undo信息和Redo信息寫入日志。(登錄王者榮耀游戲)
3)各參與者節點響應協調者節點發起的詢問。如果參與者節點的事務操作實際執行成功,則它返回一個”同意”消息;(告知組織者自己已經登錄成功)如果參與者節點的事務操作實際執行失敗,則它返回一個”中止”消息。(告知組織者自己暫時無法一起玩游戲,如自己的賬號被限制無法打排位)
提交階段
如果協調者收到了參與者的失敗消息或者超時(有人不能一起玩游戲,或者一直沒有回復),直接給每個參與者發送回滾消息(告知其他人,暫時取消游戲);否則,發送提交消息(邀請大家進入游戲房間);參與者根據協調者的指令執行提交或者回滾操作(進入房間一起玩游戲或者退出游戲去做別的事情)。
接下來分兩種情況分別討論提交階段的過程。
當協調者節點從所有參與者節點獲得的相應消息都為”同意”時:
1)協調者節點向所有參與者節點發出”正式提交”的請求(要求所有已登錄的朋友加入游戲房間)。
2)參與者節點正式完成操作,并釋放在整個事務期間內占用的資源(接受邀請,進入房間)。
3)參與者節點向協調者節點發送”完成”消息(點擊"準備",進入準備狀態)。
4)協調者節點受到所有參與者節點反饋的”完成”消息后,完成事務(進入王者峽谷)。
如果任一參與者節點在第一階段返回的響應消息為”中止”,或者 協調者節點在第一階段的詢問超時之前無法獲取所有參與者節點的響應消息時:
1)協調者節點向所有參與者節點發出”回滾操作”的請求(告知所有人取消游戲)。
2)參與者節點利用之前寫入的Undo信息執行回滾,并釋放在整個事務期間內占用的資源(退出游戲,去做自己的事情)。
3)參與者節點向協調者節點發送”回滾完成”消息(告訴組織者自己知道了,后面有機會再玩)。
4)協調者節點受到所有參與者節點反饋的”回滾完成”消息后,取消事務(取消本次游戲活動)。
2PC的缺點
以上過程其實是有一些缺點的,如
1、當參與者收到組織者的消息之后,需要登錄游戲,在游戲中等待組織者的再次邀請,這個過程比較浪費時間。
2、如果在這個過程中,組織者突然有什么事情被打斷了,那么那些已經進入游戲的參與者就可能一直等下去。
3、在所有人都登錄游戲之后,組織者通過邀請要求所有人加入他的房間,這時候如果有一些網絡異常、或者參與者沒在手機前面等情況,可能會有一部分用戶加入了房間,有一部分沒加入。
4、如果組織者在游戲中開始邀請所有參與者的時候,他邀請了第一個人之后,他和這個被他邀請的人都掉線了。這時候另外三個人就不知道到底應該怎么辦了。
以上問題,分布式系統的2PC階段一樣存在,分別對應以下問題:
1、同步阻塞問題。執行過程中,所有參與節點都是事務阻塞型的。當參與者占有公共資源時,其他第三方節點訪問公共資源不得不處于阻塞狀態。
2、單點故障。由于協調者的重要性,一旦協調者發生故障。參與者會一直阻塞下去。尤其在第二階段,協調者發生故障,那么所有的參與者還都處于鎖定事務資源的狀態中,而無法繼續完成事務操作。(如果是協調者掛掉,可以重新選舉一個協調者,但是無法解決因為協調者宕機導致的參與者處于阻塞狀態的問題)
3、數據不一致。在二階段提交的階段二中,當協調者向參與者發送commit請求之后,發生了局部網絡異常或者在發送commit請求過程中協調者發生了故障,這回導致只有一部分參與者接受到了commit請求。而在這部分參與者接到commit請求之后就會執行commit操作。但是其他部分未接到commit請求的機器則無法執行事務提交。于是整個分布式系統便出現了數據部一致性的現象。
4、二階段無法解決的問題:協調者再發出commit消息之后宕機,而唯一接收到這條消息的參與者同時也宕機了。那么即使協調者通過選舉協議產生了新的協調者,這條事務的狀態也是不確定的,沒人知道事務是否被已經提交。
總結一下,就是說2PC并不是完美的,他存在著同步阻塞問題、單點故障問題、無法100%保證數據一致性等問題。
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
總結
以上是生活随笔為你收集整理的漫话:如何给女朋友解释什么是2PC(二阶段提交)?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不想被时代抛弃,就别远离一线
- 下一篇: 如何在RCP程序中添加一个banner栏