分布式系统中可能会出现多个节点访问一个资源或者同时执行一个给定的函数,这些资源或者函数一般成为临界资源(Critical Resource),有时这些 临界资源需要在同一时刻只有一个进程执行,这就是分布式互斥.保证任何给定时刻只允许一个进程或者给定的进程去执行临界区的算法称为互斥算法.
传统的单机达到互斥的方法有互斥锁,条件变量,读写锁,共享内存,信号量,内存序,内存屏障等,这些方法在分布式系统中通通不可用,在分布式系统中消息传递是实现互斥的唯一的方法.
分布式互斥算法可以分为集中式算法(Centralized Algorithm)和分布式算法(Distributed Algorithm),其中分布式算法又可以分为基于令牌的算法(Token Based Algorithm)和基于请求的算法(Permission Based Algorithm).下来我们就来看看吧!
在所有的节点中引入一个协调者,这个协调者负责所有节点申请资源请求的调度.每个节点想要申请资源需要向协调者发送请求,如果当前节点没有人使用的话,协调者就授权这个节点进行访问.对于协调者来说维护一个队列,用先来后到的顺序为没有申请到资源的节点排序,当得到资源的节点执行完毕以后返回一个消息代表使用完毕,这个时候协调者再次分配.
集中式互斥算法在一次申请资源的交互中需要三次消息交互:
这也是集中式算法的优点,即通信成本较低,且直观,简单,所有的节点只需要于协调者通信.当然这也正是它的缺点,因为所有的压力全部落在了协调者身上,这里有两个问题:
在分布式算法中又分为基于令牌的算法和基于请求的算法,它们之间也是各有优缺点.
这里介绍Ricart-Agrawala算法,其他基于请求的算法大都在这个基础上修改.如果把一次选举的leader看做是资源的话,选举的过程其实也是一个分布式互斥算法的实现.这样看来这种基于请求的算法其实比较常见,也就是所有的节点之间互相连接,形成网状的网络拓扑结构,在每次使用资源的时候向其他节点发起资源的申请,如果获取全票同意的话则获取资源使用权,在使用的过程中也可能有其他节点同样请求资源,发送请求的双方都可以得到对方使用资源的消息,这个时候对比出时间戳最小的(基于逻辑时钟而不是物理时间戳,见另一篇文章 不可靠的时钟),即最先发起请求的获取资源访问权,得到资源访问权的节点也要维护一个队列,存储其他申请请求,在完成资源访问以后向其他申请资源的节点发送同意使用资源的消息,一般不申请资源的节点在收到其他申请资源的请求时直接同意.
从以上流程不难看出,信息的交互过程是这样的,首先我们假设集群有N个节点:
这样每个节点每次申请资源需要2(N-1)此信息交互.而且当集群内每个节点都进行资源申请的时候会有2N(N-1)次交互,也就是说随着集群的扩展,通信成本是平方上涨的.它还有以下问题:
这种基于请求的分布式互斥算法适合与节点数目少,变动不频繁的系统,且适用与P2P结构,因为每个程序之间都需要互相交互.HDFS就是一个典型的运用场景.
如下图所示,所有程序构成一个逻辑上的环结构,令牌按照顺时针(或逆时针)方向在程序之间传递,收到令牌的程序有权访问临界资源,访问完成后将令牌传送到下一个程序.若该程序不需要访问临界资源,则直接把令牌传送给下一个程序.
这样每一个节点在适用资源之前就不需要向每一个节点请求了,只需要传递令牌即可,得到令牌的节点获取资源,这样在一个周期内全部节点都有机会适用资源,不需要的话直接转发就可以了.当然这也带来一些无效的通信成本,且降低了实时性.因为就算只有一个节点请求资源,全部的节点都需要进行信息传递,而且考虑到节点宕机,每个节点也不能仅存储自己的下一位节点.令牌环算法非常适合通信模式为令牌环方式的分布式系统.
集中式算法
: 优点就是简单,易于实现,只有搭配上哨兵和主从复制可用性才说的过去,但是宕机仍会服务下线.且有单机的效率瓶颈.’分布式算法-基于请求
: 可用性强,一般也不使用全部同意,而是配置纪元搭配选举,可容忍一半以下节点宕机,比较类似与无主节点的结构.缺点就是通信成本过高.适用于临界资源使用频率较低的时候.(redis中故障转移选举执行的节点不就是这样实现的)分布式算法-基于令牌
: 通信效率高且可用性不差.使用与请求资源频繁且使用时间短的情况,缺点就是容易带来大量的无用通信.其实分布式互斥算法应用很广泛,比如选举的过程(一次只需要一个leader),Redlock(Redis官方钦点的分布式锁实现),HDFS(Hadoop的分布式文件系统),它对于我们学习分布式至关重要.
参考:
P2P结构
逻辑时钟
基于请求的分布式互斥算法 很详细
聂鹏程 分布式技术原理与算法解析