1系统
1.1 基本概念:
拓扑:无向图,结点——处理机,边——双向信道
算法:由系统中每个处理器上的局部程序构成
局部程序:用来执行局部计算和发送接收msg
一个系统或者一个算法是由n个处理器p0、p1…pn-1构成,每个处理器可以模型化为一个具有状态集Qj的状态机
状态:由每个处理器pi的变量msgs构成,每个处理器有r个信道,每个信道上有outbuf和inbuf,其中outbuf上存储的是即将发送给邻居的信息,inbuf上存储的是pi接收到的信息尚未处理
初始状态:每个inbuf为空,outbuf不为空
转换函数:处理器pi的转换函数(一个局部程序)
输入:pi可访问的状态
输出:对每个信道l,至多产生一个msg的输出
转换函数使得inbuf清空
配置:分布式系统在某点上整个算法的全局状态,用qi表示处理器pi的状态,配置用一个响亮(q0,q1,q2…qn-1)表示。
事件:系统里所发生的事情被模型化为事件,对msg传递系统
comp(i):计算事件
del(i,j,m):传递事件,m从pi传到pj
执行:系统在时间上的行为被模型化为一个执行,这是一个配置和事件交错的序列
需要满足下面四个性质:
①Safety:某个性质在每次执行中每个可到达的配置里都必须成立
②liveness:某个性质在每次执行中的某个可达配置里必须成立(也就是这个性质必须体现出来至少一次)
执行:满足所有安全性条件的序列
容许执行:满足所有活跃性条件的执行
1.2 异步系统
异步:msg传递的时间和一个处理器两个相继步骤之间的时间无固定上界
执行片段:一个有限或无限的序列 C 0 , φ 1 , C 1 , φ 2 . . . , C n C_0,\varphi_1,C_1,\varphi_2...,C_n C0,φ1,C1,φ2...,Cn
若 φ k = d e l ( i , j , m ) \varphi_k=del(i,j,m) φk=del(i,j,m),则消息 m m m从 C k − 1 C_{k-1} Ck−1的pi处理器上的 o u t b u f i [ l ] outbuf_i[l] outbufi[l]中删除,并在 C k C_{k} Ck上的 p j pj pj处理器上的 i n b u f j [ h ] inbuf_j[h] inbufj[h]中出现,l和h分别是pi和pj中信道{pi,pj}的标号
若 φ k = c o m ( i ) \varphi_k=com(i) φk=com(i),则消息在 C k − 1 C_{k-1} Ck−1的pi中的 i n b u f i [ l ] inbuf_i[l] inbufi[l]中被删除,并发送msg,也就是将转换函数指定的消息集合加到 C k C_k Ck的变量 o u t b u f i outbuf_i outbufi上
调度:调度是执行序列中的事件序列 φ 1 , φ 2 . . . . . . \varphi_1,\varphi_2...... φ1,φ2......,并非每个事件序列都是调度,例如del(1,2,m)不是调度,因为没有步骤发送(send)m。执行可以由初始配置 C 0 C_0 C0和调度唯一确定 e x e c ( C 0 , σ ) exec(C_0,\sigma) exec(C0,σ)
容许执行:处理器每个msg最终都被传递,则执行称为容许的
1.3 同步系统
定义:处理器按锁步骤执行,也就是执行被划分为轮,每轮里每个处理器才能发送和接受msg,每轮由一个传递事件和计算事件组成
容许执行:无限的执行(是指所有处理器计算都不出错)
同步系统与异步系统的区别:在一个无措的同步系统中,一个算法的执行只取决于初始配置
Broadcast:
pr: //发送者,初始化时M已经在传输状态
upon receiving no msg: //pr发送M后终止执行
terminate; //将terminated置为true
pi(i!=r,0<=i<n):
upon receiving M from parent:
send M to all children;
terminate;
时间复杂度:
1)同步模型:距离为t的节点在t时刻接收消息M
2)异步模型:距离为t的节点至多在t时刻接收消息M
Flooding算法
1)算法:从pr开始,发送M到其所有邻居。当pi第一次收到消息M时,pi发送M到除pi外
2)msg复杂性:每个结点在信道上发送M不会多于1次,所以每个信道上M至多被发送两次,最坏情况下M除了第一次接收的那些信道外,其他所有信道上M被传送两次(也就是恰好i给j发消息的同时j给i发消息)。因此可能要发送2m-(n-1)个msgs。m甚至可能多达n(n-1)/2个
3)时间复杂性:O(D) D-网直径
构造生成树
1)基本思想:
step1:首先,pr发送M给所有邻居,pr为根
step2:当pi收到了pj的消息,则pj是pi的双亲;若pi同时收到了多个邻居的M,则用一个comp事件处理所有收到的msgs,pi可以从这些邻居中任选一个作为双亲
step3:当pi确定双亲是pj时,发送< parent >给pj,并向之后收到发来M的处理器发送< reject >msg
step4:pi将M转发给所有未向自己转发M的邻居(或者已经转发但尚未收到),然后等待< parent >或< reject >,那些回应< parent >的邻居时pj的孩子
step5:当pi发出M的所有接受者均已回应< parent >或者< reject >,则pi终止
在这里可以有一个改进:若结点pi已经有了parent,则收到M不会再向Pr发送< reject >。因为pi一定会向Pr发送M,发送者会收到pi的M,也就默认收到了pi的< reject >。而同理,Pr也就不需要对Pi的M返回< reject >,因为发向Pi的M已经蕴含了M的意义。
2)代码
3)G是根为pr的有向生成树证明
①为何从根能到达每一结点?(连通)
反证法,假设存在pi可达、pj不可达且i和j相邻,又可达的充分必要条件是设置过< parent>,很容易证明矛盾
②为何无环?
假设有一个环,每个处理器都是下一个处理器的双亲,意味接收M的顺序错误,矛盾
③复杂性:此方法比flood增加了msg复杂性,但也只是常数因子
4)同步模型下,构造的一定是BFS树,并且对于具有m条边直径为D的网络,给定一个特数结点,存在一个同步算法再msg复杂性为O(m),时间复杂性为O(D)内找到一条BFS树
5)异步模型下,算法的运行时间仍为O(D)
即时是构造了从0-4的一条生成树,因为时间上不超过从0-4的M时间,仍然不超过1,因此为O(D)
6)信息的请求和收集
对于完全图,直径为D=1,边数量为m,生成树高为d,结点数量n
消息复杂度 (同步) | 消息复杂度 (异步) | 时间复杂度(同步) | 时间复杂度(异步) | |
---|---|---|---|---|
求生成树算法 | O(m) | O(m) | O(D) | O(D) |
汇集算法 | O(n-1) | O(n-1) | O(d)(d为1) | O(d)(最坏d为n-1) |
组合算法 | O(m+n) | O(m+n) | O(D+d)=O(D+1)=O(1) | O(D+d)=O(d)=O(n) |
基本思想
step1:设根节点Pr,向从未向其发送M的邻居选择一个发送M
step2:收到第一个M的pi,将发送者设为parent,并发送< parent>,对之后的所有M都回复< reject>
step3:再向从来没发过消息的一个邻居发送M,等待它的< reject>或者< parent>,并将回复< parent>的邻居加到孩子集合中(注意这是个迭代的过程,每个parent需要等待孩子结点子树建成后才能收到< parent>,然后继续给另一个孩子发M)
step4:pi向所有邻居发送过消息,终止,返回parent
定理:对于一个具有m条边,n个结点的网络,以及给定特数的结点,存在一个时间复杂度和消息复杂性均为O(m)的异步算法找到一条DFS树
基本思想:每个结点均可自发唤醒,试图构造一棵以自己为根的DFS生成树。若两棵DFS树试图链接同一节点(未必同时)时,该节点将加入根的id较大的DFS树(因此对于每个结点设置一个leader变量,初值为0,唤醒时为id)
具体过程
step1:自发唤醒时,将自己 l e a d e r i leader_i leaderi送给所有邻居
step2:当pi收到来自pj的标识符y时,比较y和 l e a d e r i leader_i leaderi
1)若 y > l e a d e r i y>leader_i y>leaderi,将 l e a d e r i leader_i leaderi置为y,并从这里继续生成y的DFS树
2)若 y < l e a d e r i y
3)若 y = l e a d e r i y=leader_i y=leaderi, P i P_i Pi已经属于标记y的DFS树中
复杂性
ID值最大的启动时间为t,具有m条边和n个点的网络,自发启动的节点有p个,则算法的消息复杂度为 O ( p n 2 ) / O ( p m ) O(pn^2) / O(pm) O(pn2)/O(pm),时间复杂度为 O ( t + m ) O(t+m) O(t+m)
基本概念
1)用处:例如死锁的时候,可以选一个leader出来删除掉;广播算法作为根
2)问题:问题从同一状态的进程配置开始,最终达到一种配置状态。每个处理器确定最终自己是否是一个leader,但只有一个处理器确定自己是leader,其他处理器都是non-leader
环的形式化模型
顺时针:向左移动( P i P_i Pi到 P i + 1 P_{i+1} Pi+1)
逆时针:向右移动( P i P_i Pi到 P i − 1 P_{i-1} Pi−1)
基本概念:
1) 匿名算法:若环中处理器没有唯一的标识符,则环选举算法是匿名的。每个处理器都有相同的状态机,msg接收者只能根据信道标号来区别。
2)(一致性的)uniform算法:算法不知道处理器数目
3)non-uniform算法:算法已知处理器数目
同步算法的不可能性(对于匿名环来说无论是一致性还是非一致性)
同步算法中处理器始终保持对称,所有处理器开始处于相同状态,改变状态也相同,因此不可能有一个处理器单独被选为leader
异步环中不存在匿名的选举算法:因此对于环系统,不存在匿名的选举算法
环系统:指派一个处理器列表按顺时针指定环,通常是通过id排列,不是通过pi的下标i来排列
非匿名算法中
一致性:每个标识符id均有一个唯一的状态机,但与环大小n无关
非一致性:每个n和一个id对应一个状态机
一致性 | 非一致性 | |
---|---|---|
匿名 | 所有处理器对应唯一的状态机 | 根据n确定状态机,但所有处理器还是相同 |
非匿名 | 每个id对应唯一状态机,但与n无关 | 根据n和id确定唯一的状态机 |
LCR算法(均匀算法)
step1:所有结点向左邻发送自己的 i d i id_i idi,并等待右邻的消息
step2:若收到消息 i d j id_j idj大于自己的id,则转发该 i d j id_j idj;若小于,则没收
step3:若某个处理器收到一个含自己标识符的msg,则宣布自己为leader,并向左转发一个终止msg
step4:当一个处理器收到一个终止msg时,向左邻转发此消息并作为non-leader终止
复杂性:最坏为 O ( n 2 ) O(n^2) O(n2),id为i可能被转发i+1次
k邻居
1)算法过程:
step0:每个结点发送1个probe消息给两个1邻居,若接收此msg的邻居id大于消息中的id,则没收;否则接收者发回一个reply msg。若一个节点从它的两个邻居收到回答msg reply,则该节点成为这个阶段的临时leader,可以进行下一个阶段
step k:在k-1阶段成为临时leader的处理器pi发送带自己id的probe消息给 2 l 2^l 2l邻居。若此msg中的id小于左右两个方向上的处理器任何一个id,则此msg被没收。若probe发送到最后一个邻居都没被没收,则最后一个处理器发送reply消息,则pi从两个方向上接收到reply消息,则称它为该阶段的临时leader,进入下一阶段
终止:接收到自己probe消息的节点终止算法成为leader,并发送一个终止msg到环上
2)
probe消息
,其中hop是跳步计数器,初始为0,每转发一个probe消息就加1,则当某一结点收到的消息为 2 l 2^l 2l,则它是邻居中的最后一个处理器,若此msg未被没收,则不在向前转发,而是向后回复reply消息
3)定理
对于每个 k ≤ 1 k\le 1 k≤1,在phase k结束时,临时leader数至多为 n 2 k + 1 \frac n {2^k+1} 2k+1n
很容易证明,每当第k个阶段结束时,必然每 2 k + 1 2^k+1 2k+1个结点都有一个leader
4)时间复杂度分析
k=0时,共需要发4n个消息,每个节点收发4个消息
k>0时,第k个阶段,最多有 n 2 ( k − 1 ) + 1 \frac n {2^(k-1)+1} 2(k−1)+1n个暂时leader,每个暂时leader给 2 k + 1 2^{k+1} 2k+1个邻居发送消息,并可能受到两个reply也同样需要传递 2 k + 1 2^{k+1} 2k+1的长度,因此消息总数为 2 k + 2 n 2 ( k − 1 ) + 1 2^{k+2}\frac n {2^(k-1) +1} 2k+22(k−1)+1n
最终还会有一个终止msg发送到环上
合计: 4 n + ∑ i = 0 l g ( n − 1 ) 2 k + 2 n 2 ( k − 1 ) + 1 + n 4n+\sum_{i=0}^{lg(n-1)} 2^{k+2}\frac n {2^(k-1) +1}+n 4n+∑i=0lg(n−1)2k+22(k−1)+1n+n,为O(nlgn)
证明对于unifrom算法,异步环里任何leader选举算法至少发送O(nlgn)个msgs
下界问题主要解决两个问题:
①选中的leader一定是环上具有最大id的处理器
②所有处理器必须知道被选中leader的id
开调度: σ \sigma σ是特定环上算法A的一个调度,若环中存在一条边使得在 σ \sigma σ中,边e上的任意方向均无msg传递,则 σ \sigma σ称为是open,e是 σ \sigma σ的一条开边。(开调度未必是容许的调度,可能是有限的事件序列,环上的处理器不一定是终止的)
因此,引发思考:我们可以将两个较小的开调度粘贴为一个较大环的开调度(因为算法是均匀的)这也会引出我们的递推式
定理:对于每个n以及每个标识符集合,存在一个由这些标识符组成的环,该环有一个A的开调度,其中至少接收M(n)个消息,这里:
{ M ( 2 ) = 1 M ( n ) = 2 M ( n / 2 ) + ( n / 2 − 1 ) / 2 \begin{cases} M(2)=1 \\ M(n)=2M(n/2)+(n/2-1)/2 \end{cases} {M(2)=1M(n)=2M(n/2)+(n/2−1)/2
PPT中证明很长,我们可以简化一下,其实就是每次将两个大小为n/2的环找到他们分别的开调度,因此可以分别断开一条边。在断边处可以再进行连接,从而将两个图拼凑在一起。对于拼凑的两条边,一条边有msg传输,一条边没有,则对于有mgs传输的那条边上至少有一半的msg在其中一个环上又传输了一次(因为可能leader在另一个环上,非leader所在的环需要再进行msg交流获取信息),这样就多出了至少 ( n / 2 − 1 ) / 2 (n/2-1)/2 (n/2−1)/2
上界:分别对于均匀和非均匀提出O(n)的算法,但这里运行时间并非只和n有关,还与算法使用的非普通的id相关
下界:讨论只基于比较符的算法和时间受限(若干轮终止,轮数只依赖于环大小,不依赖于id值)的算法,至少需要O(nlgn)
(显然这里上界和下界的时间有点奇怪,但是对于上界来说,时间不仅仅和n有关)
1)非均匀的:要求环中所有的结点开始于同一轮(需要知道n)
2)均匀的:结点可开始于不同轮,弱同步模型(无需知道n)
在phase i阶段,若一个结点的id是i则它绕环发送一个msg并作为一个leader终止,其他结点收到msg,则再转发此msg后作为non-leader终止。否则进入下一个阶段(注意没有任何消息传送)
每个msg分为两个阶段:
step1:唤醒:由一个结点发出的唤醒msg包含该结点的id,该msg以每轮一边的正常速率周游,那些接收到唤醒msg之前未启动的结点不参与选举
step2:延迟:当来自结点id为i的msg到达一个醒着的节点时,该msg以 2 i 2^i 2i速率周游,即每个收到该msg的结点将其延迟 2 i − 1 2^i-1 2i−1轮后再转发
没收规则:
①一个参与的结点收到msg时,若该msg里的id大于当前已经看到的最小的id(包括自己),则没收该msg
②一个转发的结点收到msg时,若该msg里的id大于当前已经看到的最小id(除自己),则没收该msg
2)分析算法复杂度
第一类:第一阶段的msg
第二类:第二阶段的msg(在最终leader的msg进入第二阶段之前)
第三类:第二阶段的msg(在最终leader的msg进入第二阶段之后)
第一类:很明显能够看出第一阶段的msg碰到唤醒的结点就不会再转发,因此最多环一圈把所有结点都唤醒,为O(n)
第二类:首先我们明确一个定理,在任何主动唤醒的结点的n轮之后,它发送的msg必定进入第二阶段。因此,我们必然在n轮内找到所有的第二类的msg。又因为这个阶段的msg不包括自己的msg(因为自己还没进入第二阶段),因此最多有n-1个结点发送这些msg,每个id都不相同(且不可能为0),因此最多为 ∑ i = 1 n − 1 n / 2 i ≤ n \sum_{i=1}^{n-1}n/2^{i}\le n ∑i=1n−1n/2i≤n
第三类:首先明确一个定理,对于第三类msg,他们也至多绕环一圈,经历的总轮数为 n ∗ 2 i d i n*2^{id_i} n∗2idi,在这些轮数中另一个非唤醒的 m s g < i d j > msg
msg<idj>转发次数至多为 n ∗ 2 i d i − i d j n*2^{id_i-id_j} n∗2idi−idj。那我们可以假设i为最小id的那个处理器,则总共转发msg数量为 ∑ j = 0 n − 1 n 2 i d i − i d j ≤ ∑ k = 0 n − 1 n 2 k ≤ 2 n \sum_{j=0}^{n-1}\frac{n}{2^{id_i-id_j}}\le \sum_{k=0}^{n-1}\frac n{2^k}\le 2n ∑j=0n−12idi−idjn≤∑k=0n−12kn≤2n
显然这两种算法都依赖于id的值,若id很大时,可能时间复杂度会很差
异步环中的下界只对均匀算法有效,同步环的下界对均匀算法和费均匀算法都有效
终极定义:一个算法是基于比较的,若对每队序等价的环R1和R2,每对匹配的节点在exec(R1)和exec(R2)里的行为均相似(该定义说明这一算法只与环上标识符之间的相对次序相关,而与具体id值无关,这就是基于比较的真正意义)
2.1 概念:
1)主动轮:某一轮在任何序等价的环上均无msg发送,则该轮是无用的,否则是主动轮(因此注意,即使是在不一致的同步环算法中,前k轮也一定是有用的,因为一定存在一个序等价的环村子id为0的情况,这种情况下一定会发msg)
2)性质:一个结点在第k个主动轮之后的状态只依赖于它的k-邻居
3)定理:具有序等价的k邻居的结点,k个主动轮结束后,所有结点的k-邻居内的所有结点处于相同的状态
4)空隙环:环R中,每两个id之间均有n个未使用的标识符(n是环的大小)
2.2 定理3.17:
R是有空隙环,Pi和Pj是R上具有序等价k邻居的两个结点。则Pi和Pj正在exec®的第1到rk轮里具有相似的行为
构造R’方式:
①R’中的Pj和R中的Pi有相同的k邻居
②R’中的标识符唯一
③R’和R序等价,R’中Pj匹配于R中的Pj
k=1,n=8
有结论:(哪哪都相似)
1)R上的Pi和R’上的Pj在前k个主动轮行为相似
2)R上的Pj和R’上的Pj在前k个主动轮行为相似
3)R上两节点的k邻居序等价,则其行为在前k个主动轮相似
2.3 定理3.18 对于每个n>=8,存在一个大小为n的环Sn,使得对于每个基于比较的同步leader算法A,在Sn上A的容许执行里发送msg的数目为O(nlgn)
证明方法:先构造高度对称的Sn,再计算Sn上发送的msg总数
1)构造Sn
step1:定义大小为n的环 R n r e v R^{rev}_n Rnrev,对于 i ∈ [ 0 , n − 1 ] i\in [0,n-1] i∈[0,n−1],每个Pi对应的id为rev(i),rev(i)是i的二进制表示的逆序列
很明显能够看出,这里将环分为 2 i 2^i 2i个片段,每个片段必然序等价
证明方法:利用二进制逆序的性质,分为 2 i 2^i 2i个片段,每个片段有 2 j 2^j 2j个元素,因为逆序,所以这 2 j 2^j 2j个元素被放在了id的开头j位,因此对于每个片段的开头j位都是一一对应的,而后面i位则在一个组内一定不会变,因此片段处处序等价
step2:从 R n r e v R^{rev}_n Rnrev构造Sn,将 R n r e v R^{rev}_n Rnrev上每个id乘以n+1再加上n所获得的Sn就是有空隙环,且不改变片段的序等价性
2)证明Sn上发送的msg总数
引理3.19:Sn中序等价的邻居集数目:对于k邻居集(kn 2 ( 2 k + 1 ) \frac n {2(2k+1)} 2(2k+1)n
引理3.20:主动轮数目下界:至少为T=n/8(证明通过3.19证明若主动轮超过这个值,则leader所在的T邻居集个数不止一个 n 2 ( 2 T + 1 ) \frac n {2(2T+1)} 2(2T+1)n,则leader也会不止一个!因为序等价)
引理3.21:每个主动轮主动发送msg数目的下界( n 2 ( 2 k + 1 ) \frac n {2(2k+1)} 2(2k+1)n)因为主动轮必有msg发送,则这些个邻居集都应该有msg发送
有上述所有定理可以看出,exec(Sn)里发送的msg总数至少为 ∑ k = 1 n / 8 n 2 ( 2 k + 1 ) ≤ ∑ k = 1 n / 8 n 6 k ≤ n 6 l n n 8 \sum_{k=1}^{n/8} \frac n {2(2k+1)} \le \sum_{k=1}^{n/8} \frac n {6k} \le \frac n 6 ln \frac n 8 ∑k=1n/82(2k+1)n≤∑k=1n/86kn≤6nln8n
还需要注意的是,因为需要有空隙环,所以对于大小为n的环来说,所取标识符Sn中最小标识符为n,最大标识符为 n 2 + n − 1 n^2+n-1 n2+n−1,并且最后一个标识符后面还需要空n位,则集合大小为 n 2 + 2 n n^2+2n n2+2n,集合为 0 , 1 , . . . , n 2 + 2 n − 1 {0,1,...,n^2+2n-1} 0,1,...,n2+2n−1
3.1 定义:若对任意的n,当标识符取自于自然数集合时,在所有大小为n的环上同步算法A的最坏时间是有界的,则称A为时间有界
3.2 定义:设R1和R2是任意两个大小为n的序等价的环,则每对匹配的结点在exec(R1)和exec(R2)的第1至t轮有相似的行为,则同步算法A对于环大小为n的标识符集合S是基于t比较的。(也就是t轮前终止的算法,它和基于比较的算法在所有轮上完全相同)
证明
Ramsey定理:集合S,分为很多个k大小的子集;给子集中每个点着t种色,则必存在若干个子集的着色方式完全相同
用在上述证明中
定理:A是一个运行时间为r(n)的时间受限的同步算法,对于每个n,存在一个具有 n 2 + n n^2+n n2+n个id的集合Cn,使得A是Cn上的一个基于r(n)比较的算法
证明:因为Cn中一定有n个等价类,也就是n个序等价可以比较的环,由上面t比较的定义,可以得证
3.3 终极补充:因为上面的标识符是自然数 0 − n 2 + 2 n − 1 0-n^2+2n-1 0−n2+2n−1,因此我们想要推广到一般形式,很简单,只要将任意一个{c0,c1,c2…,cn-1}和{0,1,2…n-1}一一对应即可(序等价)
分布式系统缺乏全局信息的原因:非即时通信、相对性影响、中断
1 基础概念
1)分布式系统构成:
P={P1,P2,…,Pn}:处理器集合
ϵ \epsilon ϵ:全体事件的集合
ϵ p \epsilon_p ϵp:发生在p上的所有事件
2)次序:
e 1 < e 2 e_1 < e_2 e1<e2:事件e1发生在e2之前
e 1 ≤ e 2 e_1 \le e_2 e1≤e2:事件e1发生在e2之前,I为信息源
3)定序:分为两类(同一个结点和消息m相关事件)
①发生在同一节点上的事件(e1和e2)满足全序:记为 e 1 ≤ p e 2 e_1\le_p e_2 e1≤pe2或者 e 2 ≤ p e 1 e_2\le_p e_1 e2≤pe1
②e1发送消息m,e2接收m,则 e 1 < m e 2 e_1<_m e_2 e1<me2
4)Happens-before关系( < H <_H <H)
①H关系继承所有的p和m关系,并且具有传递性,
②并且对于 e 1 < H e 3 e_1<_He_3 e1<He3表示一个事件因果链,也就是e1发生在e3前面
③ < H <_H <H是一种偏序关系,存在并发事件不能由此定义
2 H-DAG
注意这里面每个节点P上的事件之间也要添加箭头
my_TS=0
On event e:
if (e.receive(m)):
my_TS = max(my_TS, m.TS)
my_TS++
e.TS = my_TS
if (e.send(m)):
m.TS = my_TS
尤其要注意的是:对于每次事件e,我们都会将局部事件自增1,并赋值给e(注意是自增1后再赋值给e)
3. Lamport算法赋值的时间戳是因果相关的(也就是时间顺序就是因果顺序)
4. Lamport算法改进:
1)因为对于并发事件无法比较,因此系统中所有事件还不是全序
2)我们可以将节点地址作为时间戳的低位
5. 缺点:还是不能判断并发事件的因果关系(1.3<2.1)
问题提出
这个图中可以看出,P3想要访问O,但是P1已经将其迁移到P2,但P2尚未收到,因此P3就会报错。
错误原因是违反因果序,也就是 M 1 < H M 3 M1<_H M3 M1<HM3,但是 r ( M 3 ) < P 2 r ( M 1 ) r(M3)<_{P2}r(M1) r(M3)<P2r(M1)
违反因果序检测
定义时戳VT具有比较函数满足 e 1 < H e 2 e_1<_H e_2 e1<He2 iff e 1 . V T < V e 2 . V T e_1.VT<_Ve_2.VT e1.VT<Ve2.VT
其中VT是一个大小为M(M为处理器个数)的数组,e.VT[i]=k表示在结点i上,因果关系上e之前有k个事件
尝试画一画他们各自的VT?
具体算法过程比较简单,其实就是画出每个处理器上一定发生在自己之前的事件数量即可(在自己处理器上要包括自己!!)
若e1.VT和e2.VT无法比较,则e1和e2是并发的
因果序检测
能够看出M1发来消息的时间戳是100,M3发来消息的时间戳是303,因此M1后于M3到是违反因果序的;
并且100页小于局部时戳(313和323),因此M1应该先于之前的事件
为了保证通信不违反因果关系,我们可以通过抑制过早到达的msg
对于处理器P:
delivery_list={}
当接收从p发来的消息m时:
if blocked[p] == none:
earliest[p] = m.VT
将m放到blocked[p]的队尾
while(存在k使得blocked[k]不为空,则对于每一个除了P和k之外的所有earliest[i][i]都必须大于earliest[k][i]){
将blocked[k]队头元素m'出队,加入到delivery_list
if(blocked[k]非空)
把earliest[k]置位m'.VT
else:
earliest[k]+=1_k
deliver the msg
}