有通信鏈路故障的同步完全圖網絡下,進程一致性算法
問題形式化描述:
有n個進程,每個進程可以選擇(0,1)中的某個值,要求這些進程做決定前滿足
- 一致性(每個進程的最終結果要相同)
- 有效性:如果所有進程都從0開始,那麼0就是唯一可能的決定值; 如果進程都以1作爲初值並且所有消息都被傳遞,則1是唯一的決定值。(也就是說,初始狀態有0,也有1的狀態下,可以最終結果都是0或者最終結果都是1)
- 終止性:所有進程最後都會做出決定。
隨機化算法RandomAttack algorithm:(有一定的失敗概率)
前提假設:
- 進程之間是完全圖
- 爲了計算算法失敗的概率,假設通信鏈路發生故障並不是隨機發生的,而是由一個“對手”指定的
形式化描述進程之間的關係:
定義進程之間滿足(i,k)上的偏序關係⊰,i是進程號,k是時間:
- ( i,k` )⊰( i,k ) 當 k` <= k時。
- 如果 進程 i 與 進程 j 之間有消息傳遞(i 傳給 j),則 (i, k-1)⊰ (j, k)
- ⊰可以傳遞。
定義每個進程i在任意時間k的level:
- level(i,0) = 0
- 某個k>0且存在某個j!=i,使得(j,0)⊰(i,k)不成立(存在j進程一開始就無法向i進程發消息),level(i,k) = 0
- 某個k>0且對於所有j!=i,使得(j,0)⊰(i,k),則Lj表示max{ level(j,k`):(j,k`)<(i,k) }(在k時刻傳遞消息給i的所有j進程的之前狀態(j,k`)中level最大的,而不能理解爲j最後一次向i傳遞消息後的level), level(i,k) = 1+min{ Lj:j!=i }(傳消息給i的所有進程j,如果Lj最小的達到了n,i的level就是n+1)
對於任意一個良好的通信模式,任意一個時刻k,任意兩個進程 i,j, | level( i, k ) - level( j, k ) | <= 1:
證明分析:
觀察下面這個通信過程的圖:系統每輪通信都是進程先把自己的level廣播,然後接受其他進程的level,然後更新自己的level:
方塊代表進程,箭頭代表進程間的通信,每個進程中有進程編號,進程level,和維護系統所有進程有史以來最高級別的L向量
首先我們能得知,level是單調遞增的。
如果鏈路不發生故障,每個進程中維護的level之差肯定不超過1,如圖1,圖2
只要有某條鏈路發生故障,
如果這個故障導致某個進程的level比其他進程慢一拍,如圖3;在下一次信息傳遞中,由於level(i,k) = 1+min{ Lj:j!=i },其他進程會立刻停止level遞增,如圖4,等進程b跟上隊伍一樣。
random attack算法描述:
- 算法在每一個進程內進行;
- 每個進程維護一個三元組消息 msg(L,V,key),L是向量,保存所有進程的級別[ 0, r ],V是向量,保存所有進程的初值,[0, 1, undefined],key是[1, r]中的一個整數,或者是undefined
- 每個進程有一個最終決定decision。
每個進程初始化msg
i 是本進程,j 是其他進程
V[i] = 初始值0或1 V[j] = undefined
L[i] = 0 L[j] = -1
key = undefined
執行流程:
if (i == 1 && round == 0){
key = random();//進程1隨機產生一個key
}
for( round = 0; round<r; ++round ){
send(msg(L, V, key));//發送消息msg
msg(L1, V1, key1) = recv();//接收其他進程發來的消息
for(每一個其他進程 j){
L[j] = 本進程 i 收到的所有msg中 L1[j] 的最大值(這可以保證L中的數值差距也在1之內)
如果V1[j] 不是 undefined,V[j] = V1[j]
}
L[i] = min{ L[j] }+1;
}
if( key != undefined && L[i] >= key && 對所有的j,V[j] == 1 ){
decision = 1;
} else{
decision = 0;
}
RandomAttack,分析,爲什麼這個算法在一定的概率下可以保證一致性,有效性,終止性
- 終止性,顯然
- 有效性 和 一致性:
如果random選擇出來的 key > max(level),或者某些進程以初值0開始,則所有進程decision = 0
如果random選擇出來的 key <= min(level),且所有進程初值是1,則所有進程decision = 1
只有當random選擇出來的 key == max(level)的時候,纔有可能出現不一致,max(level)是“對手”指定的,key是{ 1,r }中隨機抽選的,所以算法不一致的概率是1/r
算法的形象描述:
每個進程就像一個個人,手拉手。在一個長n米的路上走,在這段路中隨機選了一個標誌key。規定只能執行n個回合,每個回合大家可以選擇走或者不走。
每個回合,所有進程一起吼自己的值是0還是1,並且聽別人的值並記下來。
如果一個人記住了所有人的值,就可以往前走。否則,就有可能停下來犯傻。
如果有一個進程停下來發傻,大家就都停下來等他。
n回合之後 :如果一個進程記錄下所有人是1,並且自己邁過了標誌key,就決定1,否則決定0。
每個回合,所有進程一起吼自己的值是0還是1,並且聽別人的值並記下來。
如果一個人記住了所有人的值,就可以往前走。否則,就有可能停下來犯傻。
如果有一個進程停下來發傻,大家就都停下來等他。
n回合之後 :如果一個進程記錄下所有人是1,並且自己邁過了標誌key,就決定1,否則決定0。
這樣,只有一種情況會發生不一致:
記錄的所有進程值都是1,但是有一些進程越過了key,有一些進程沒有越過key,所以越過key的進程決定1,沒越過的決定0.
但是進程之間的差距不超過1步,所以這種情況出現的概率只有1/n
?多一句嘴,會不會出現這種情況:
所有進程都越過了key,但是由於鏈路故障,有一些進程聽到了所有的喊話,知道其他進程都是1,所以決定1;一些進程沒有聽到所有喊話,所以決定是0。
不可能:原因是隻要key不在起點,而是在路中間,進程越過key就說明進程向前邁了步,邁步的前提是key收齊了所有別的進程的信號。
記錄的所有進程值都是1,但是有一些進程越過了key,有一些進程沒有越過key,所以越過key的進程決定1,沒越過的決定0.
但是進程之間的差距不超過1步,所以這種情況出現的概率只有1/n
?多一句嘴,會不會出現這種情況:
所有進程都越過了key,但是由於鏈路故障,有一些進程聽到了所有的喊話,知道其他進程都是1,所以決定1;一些進程沒有聽到所有喊話,所以決定是0。
不可能:原因是隻要key不在起點,而是在路中間,進程越過key就說明進程向前邁了步,邁步的前提是key收齊了所有別的進程的信號。