分布式算法的基本属性
一般来说,去中心化的算法具有以下特性。
- 相关信息分布在多台计算机上。
- 进程只根据本地信息做出决定。
- 不应该有一个关键点,其失败会导致算法的崩溃。
- 没有共同的时钟或其他准确的全球时间来源。
- 前三点都指出,在一个地方收集所有的决策信息是不允许的。 在没有集中化的情况下确保同步,需要采取不同于传统操作系统的方法。
- 最后一点也非常重要--在分布式系统中,要及时达成协议一点也不容易。
时间同步:克里斯蒂安的算法,伯克利算法
逻辑时钟:兰波特
为了使逻辑时钟同步,Lamport定义了 "以前发生 "的关系。 表达式a-->b读作 "a发生在b之前",意味着所有进程都认为事件 "a "先发生,然后是 "b"。这种关系在两种情况下可以很明显:
- 如果这两个事件发生在同一个过程中。
- 如果事件 "a "是一个进程中的发送操作,事件 "b "是另一个进程对该消息的接收。
- 关系-->是传递性的。
- 如果两个事件 "x "和 "y "发生在不交换信息的不同进程中,那么x-->y和y-->x的关系是不正确的,这些事件被称为并发的。
引入一个逻辑时间C,使得
如果a-->b,则C(a)<C(b)
算法。
- 时钟Ci随着Pi过程中的每个事件而增加其值。Ci = Ci + d (d > 0, 通常等于1)
- 如果事件 "a "是进程Pi发送的消息 "m",那么时间戳tm=Ci(a)被写进这个消息。当进程Pj收到这个消息时,其时间被修正如下。Cj = max(Cj,tm+d)
选举一名协调员:欺负人的算法
- 如果程序发现协调人需要很长的时间来回应,它就会启动一个选举。P程序执行选举的情况如下。
- P向所有编号高于自己的进程发送一个 "选举 "信息。
- 如果没有回应,P就被认为是赢家,成为协调人。
- 如果其中一个数字较高的进程作出回应,它就会接管选举。 过程P对选举的参与结束。
- 在任何时候,该进程都可能收到来自较低编号对等体之一的 "选举 "消息。 在这种情况下,它发送一个 "OK "响应,让它知道它还活着并接管了选举的运行,然后开始选举(如果此时它还没有运行)。 因此,所有进程都将停止选举,只有一个进程除外--新的协调人。他将自己的胜利通知了所有人,并以 "协调员 "的口吻上任。
- 如果一个进程被关闭,然后想重新参与,它就会举行一次选举(因此该算法的名称)。
选举一名协调员:循环算法
- 该算法是基于使用一个环(物理或逻辑)。
- 每个进程都知道循环列表中的下一个进程。 当一个进程检测到没有协调者时,它向下一个进程发送一个带有其编号的 "EXCEPT "消息。如果下一个进程没有响应,信息就会被发送到它后面的进程,以此类推,直到找到一个工作进程。每个正在运行的进程将自己的号码添加到正在运行的进程列表中,并将信息进一步绕圈转发。
- 当进程在列表中找到自己的编号(圆圈完成)时,它将消息类型改为 "协调者",并进行循环,通知所有人关于工作进程的列表和协调者(列表中编号最高的进程)。
- 一旦完成了这一圈,信息就会被删除。
相互排斥:集中式算法
- 所有进程都向协调者请求进入关键部分的许可,并等待这一许可。 协调器按照收到请求的顺序提供服务。
- 获得许可后,该过程进入了关键部分。 在离开关键部分时,它通知协调人。
- 每个关键部分的信息数量为3。
- 该算法的缺点是集中式算法的通常缺点(协调器崩溃或信息过载)。
分散的基于时间戳的算法
进入一个关键部分
- 当一个进程想进入一个临界区时,它向所有进程发送一个包含临界区名称、进程号和当前时间的请求消息。
- 发送请求后,该进程等待每个人给予它许可。在得到所有人的许可后,它进入了关键部分。
流程在收到请求时的行为
- 当一个进程收到一个请求消息时,根据它与指定的关键部分有关的状态,它以下列方式之一行事。
- 如果收件人不在关键部分内,也没有请求进入该部分的许可,它就会向发件人发送一个 "OK "消息。
- 如果收件人在一个关键部分内,它不会响应,但会记住该请求。
- 如果收件人发出了进入该部分的请求,但还没有进入,它就会比较其请求的时间戳和其他人的时间戳。时间戳小的一方获胜。如果外国请求获胜,该进程将发送一个 "OK "消息。 如果外国请求有更大的时间戳,则不发送响应,外国请求被记住。
退出一个关键部分
- 在退出部分后,它向所有它记住的请求的进程发送一个 "OK "消息,然后删除所有记住的请求。
- 每节传递的信息数量是2(n-1),其中n是进程的数量。
- 另外,一个临界点被n个点所取代(如果某些过程停止运作,缺乏来自它的决议将使所有人停止)。
- 最后,如果在集中式算法中存在协调器超载的危险,在这种算法中,任何进程的超载都会导致同样的后果。
- 对算法的一些改进(例如,等待大多数人的许可,而不是所有的人)需要不可分割的广播信息。
该算法被命名为Ricart-Agrawala。 需要对系统中的所有事件进行全局时间排序。
带有圆形标记的算法
- 所有的过程都形成了一个逻辑环,每个人都知道谁在遵循它们。
- 一个令牌在环中循环,授予进入一个关键部分的权利。
- 在收到令牌后(通过点对点消息),进程要么进入关键部分(如果它在等待许可),要么进一步转发令牌。
- 在离开关键部分后,令牌被转发,不允许用同一令牌再次进入该部分。
广播标记算法(Suzuki-Kasami)
该标记包含。
- 请求队列。
- 数组LN[1...N],包含最后满足的请求的数量。
进入关键部分
- 如果请求关键部分的进程Pk没有令牌,它将增加其请求序列号RNk[k]并发送一个包含进程号(k)和请求号(Sn = RNk[k])的广播消息 "REQUEST"。
- 如果进程Pk有(或收到)一个令牌,它就会执行关键部分。
收到请求时的处理行为
- 当进程Pj收到来自进程Pk的请求信息时,它设置RNjj[k]=max(RNjj[k],Sn)。
- 如果Pj有一个空闲的令牌,它只在RNjj[k]==LN[k]+1(请求不老)时才将其发送给Pk。
退出Pk进程的关键部分。
- 将令牌中的LN[k]设置为等于RNk[k]。
- 对于RNk[j]=LN[j]+1的每个Pj,它将其标识符添加到请求标记队列中(如果它还没有在那里)。
- 如果请求标记队列不是空的,那么第一个元素将被移除,标记将被发送到相应的进程(其请求是队列中的第一个)。
树标算法(Raymond)
所有进程都表示为平衡的二叉树。每个进程都有一个来自自身和相邻进程(第1、第2或第3)的请求队列和一个指向令牌所有者的指针。
关键部门的入口
- 如果有一个令牌,进程就执行COP。
- 如果没有令牌,这个进程:
- 将其请求放在请求队列中。
- 向令牌所有者发送一个 "REQUEST "消息,并等待消息的到来。
进程在接收信息时的行为
不在CW中的进程必须对两种类型的信息做出反应--"MARKER "和 "REQUEST"。
A) "MARKER "信息已经到达。
- М1. 从队列中取出第1个请求,并将令牌发送给其作者(概念上,可能是发送给自己)。
- М2. 将指针的值向标记处改变。
- М3. 从队列中排除一个查询。
- М4. 如果队列中还有任何请求,就向标记者发送 "REQUEST "消息。
B) 收到REQUEST信息。
- 将请求放入队列。
- 如果没有标记,则向标记处发送 "REQUEST "信息,否则(如果有标记)转到M1点。
退出关键部分
- 如果请求队列是空的,退出时不做任何事情,否则 - 转到M1点。