1:什么是分布式互斥
分布式进程常常需要协调他们的动作,如果一组进程共享一个或一组资源,那么访问这些资源时,需要互斥来防止干扰并保证一致性。在分布式系统里,这种排他性的资源访问方式,叫作分布式互斥(Distributed Mutual Exclusion),而这种被互斥访问的共享资源就叫作临界资源(Critical Resource)。
2:互斥算法
2.1 中央服务器算法
中央服务器算法也叫集中式算法,上面提到的互斥机制,最简单的方法是使用一个服务器来授权访问临界资源的许可,该服务器充当 “协调者” 的角色。每个进程在访问临界资源时,先给该协调者发送一个请求并等待协调者应答。如果当前没有其他进程使用这个临界资源,协调者直接应答该进程请求。如果有其他进程在使用临界资源,则协调者不会立即应答,而是将该请求放入队列,并为该请求 “排号”。如果有进程使用完资源,则通知协调者,协调者从 “排号” 的队列里取出排在最前面的请求,并给它发送授权消息。拿到授权消息的程序,可以直接去访问临界资源。
如图所示,程序 1、2、3、4 为普通运行程序,另一个程序为协调者。当程序 2 和程序 4 需要使用临界资源时,它们会向协调者发起申请,请求协调者授权。
如果此时,程序 3 正在使用临界资源。协调者会根据程序 2 和 4 的申请时间顺序,依次将它们放入等待队列。在这个案例里,程序 4 的申请时间早于程序 2,因此排在程序 2 的前面。
程序 3 使用完临界资源后,通知协调者释放授权。此时,协调者从等待队列中取出程序 4,并给它发放授权。这时,程序 4 就可以使用临界资源了。
从上述流程可以看出,一个程序完成一次临界资源访问,需要如下几个流程和消息交互:向协调者发送请求授权信息,1 次消息交互;协调者向程序发放授权信息,1 次消息交互;程序使用完临界资源后,向协调者发送释放授权,1 次消息交互。
因此,每个程序完成一次临界资源访问,需要进行 3 次消息交互。
可以看到,集中式互斥算法的优点在于简单,容易理解和实现,并且所有进程只需要和协调者进行交互,进程之间无需通信。但是,也存在一定问题:
1:协调者服务器会成为系统的性能瓶颈,协调者处理的消息数量会随着需要访问的临界资源的进程数量线性增加;
2:由于是集中式处理,协调者服务器如果出现单点故障,会导致所有进程均无法访问临界资源,导致整个系统不可用。
因此,如果使用中央服务器算法(集中式算法),那么要考虑选择性能好并且可靠性高的服务器来运行协调者。
总结:集中式算法具有简单、易于实现的特点,但可用性、性能易受协调者影响。在可靠性和性能有一定保障的情况下,比如中央服务器计算能力强、性能高、故障率低,或者中央服务器进行了主备,主故障后备可以立马升为主,且数据可恢复的情况下,集中式算法可以适用于比较广泛的应用场景。
2.2 分布式算法
分布式算法又称使用组播算法和逻辑时钟算法,Ricahrt和Agraawala 在1981年开发了一个基于组播实现的N个对等进程间互斥的算法。该算法的基本思想是要进入临界资源的进程组播一个请求消息,并且只有在其他进程都应答了这个消息时才能进入。
举例,如下图所示:程序 1、2、3 需要访问共享资源 A。在时间戳为 8 的时刻,程序 1 想要使用资源 A,于是向程序 2 和 3 发起使用资源 A 的申请,希望得到它们的同意。在时间戳为 12 的时刻,程序 3 想要使用资源 A,于是向程序 1 和 2 发起访问资源 A 的请求。
如图所示,此时程序 2 暂时不访问资源 A,因此同意了程序 1 和 3 的资源访问请求。对于程序 3 来说,由于程序 1 提出请求的时间更早,因此同意程序 1 先使用资源,并等待程序 1 返回同意消息
如图所示,程序 1 接收到其他所有程序的同意消息之后,开始使用资源 A。当程序 1 使用完资源 A 后,释放使用权限,向请求队列中需要使用资源 A 的程序 3 发送同意使用资源的消息,并将程序 3 从请求队列中删除。此时,程序 3 收到了其他所有程序的同意消息,获得了使用资源 A 的权限,可以使用临界资源。
从上述流程可以看出,一个进程完成一次临界资源的访问,需要进行如下的信息交互:向其他 n-1 个进程发送访问临界资源的请求,总共需要 n-1 次消息交互;需要接收到其他 n-1 个进程回复的同意消息,方可访问资源,总共需要 n-1 次消息交互。因此,一个进程访问临界资源至少需要 2*(n-1) 次消息交互。
如果现在系统中的 n 个进程都要访问临界资源,则会同时产生 2n*(n-1) 条消息。因此,在大型系统中使用分布式算法,消息数量会随着需要访问临界资源的进程数量呈指数级增加,容易导致高昂的“沟通成本”。
综上,分布式互斥算法根据“先到先得”以及“投票全票通过”的机制,让每个程序按时间顺序公平地访问资源,优点是简单粗暴、易于实现。但是这个算法可用性很低,主要包括两个方面的原因:
- 当系统内需要访问临界资源的进程增多时,容易产生“信令风暴”,也就是程序收到的请求完全超过了自己的处理能力,而导致自己正常的业务无法开展。
- 一旦某一程序发生故障,无法发送同意消息,那么其他程序均处在等待回复的状态中,使得整个系统处于停滞状态,导致整个系统不可用。所以,相对于集中式算法的协调者故障,分布式算法的可用性更低。
针对分布式互斥算法的可用性低的缺陷,改进的办法是:如果检测到一个程序故障,则直接忽略这个程序,无需再等待它的同意消息。但同时,每个进程都需要对其他进程进行故障检测,这也带来了更大的复杂性。
因此,分布式算法适合节点数目少,且变动不频繁的系统,并且每个进程之间均需通信交互,因此适合P2P结构的系统。
我们熟悉的Hadoop分布式系统,其中的HDFS文件修改就是一个典型的分布式算法的场景。
- 计算机 1 向计算机 2、3 发送文件修改请求;
- 计算机 2、3 发现自己不需要使用资源,因此同意计算机 1 的请求;
- 计算机 1 收到其他所有计算机的同意消息后,开始修改该文件;
- 计算机 1 修改完成后,向计算机 2、3 发送文件修改完成的消息,并发送修改后的文件数据;
- 计算机 2 和 3 收到计算机 1 的新文件数据后,更新本地的备份文件。
2.2 令牌环算法
所有进程构成一个环结构,令牌按照顺时针或逆时针方向在进程之间传递,收到令牌的进程有权限访问临界资源,访问完成后将令牌传送到下一个进程;如果进程不需要访问临界资源,则直接把令牌传送给下一个进程。
在分布式领域,这个算法叫做令牌环算法,也成为基于环的算法。
如图所示:
在使用临界资源前,不需要像分布式算法那样挨个征求其他进程意见了,相对而言,令牌环算法里单个进程具有更高的通信效率,在一个周期内,每个进程都能访问到临界资源,算法公平性更好。但是优点也是缺点,因为无论环中的进程是否想要访问资源,都需要接受并传递令牌,导致带来一些无效的通信。比如有100个进程,那么进程1访问临界资源后,即使其他99个进程不需要访问,也必须要等令牌子在其他99个进程传递完成后,才能访问资源,降低了系统的实时性。
综上所述,令牌环互斥算法适合通信模式为令牌环方式的分布式系统。算法的公平性高,在改进单点故障后,稳定性也很高,适用于系统规模较小,并且系统中每个程序使用临界资源的频率高且使用时间比较短的场景。
3:优缺点总结
算法 | 方法 | 优点 | 缺点 | 应用场景 |
---|---|---|---|---|
集中式方法 | 引入一个协调者,将所有请求者进行排序,先到先得 | 简单易于实现,通信高效 | 可用性低,存在单点故障,性能受协调者影响 | 在协调者的性能和可靠性受保障的情况下,可适用较广泛的场景 |
分布式算法 | 征求其他进程意见同意后,才可以访问临界资源 | 适用性高 | 通信成本高,复杂度高 | 临界资源适用率低并且规模比较小的场景 |
令牌环算法 | 所有进程组成一个环,轮流使用临界资源 | 单个参与者通信效率高,可用性高 | 当参与者对临界资源使用频率比较低,导致无效的通信比较多 | 系统规模比较小,并且系统中每个进程使用共享资源频率 |
4:问题延伸
针对中央服务器算法(集中式算法)、分布式算法和令牌环算法存在的缺陷,有哪些可以改进的地方?
- 集中式算法:可参照redis集群通信模式,通过哈希算法将大量的请求分散到不同的master,以处理大量请求,每个master由小集群主从节点来保障单点故障
- 分布式算法:分布式算法可在集群中过半数同意就识为其同意,降低通信数,如分布式选举场景
- 令牌环算法:可根据参与者使用频率列出权重,结合平滑加权轮询算法选出下一个参与者