分布式同步化

事件顺序的同步化

在集中式系统中,时间是明确的。当进程想知道时间时,它就进行一次系统调用,然后系统内核就告诉它。如果进程A询问时间,稍后进程B也询问时间,那么进程B获取的时间值将比进程A获取的时间值大,或者可能相等。但无论如何不会小于后者。
由于在分布式系统中,可能所有的机器没有同步,因此在分布式系统中实现事件的顺序比较困难。

分布式系统中时钟同步的解决方法

逻辑时钟

逻辑时钟不是分布式系统中真实的时钟时间。而是一个逻辑时间,即事件发生先后顺序的逻辑值。也可以理解为版本号。

逻辑时钟是由Lamport提出的。为了同步逻辑时钟,Lamport定义了一个称为“先发生(happens-before)”的关系。表达式a->b读作“a在b之前发生”,意思是所有进程一致认为事件a先发生,然后事件b才发送。
先发送关系有两种情况:
(1)如果a和b是同一个进程中的两个事件,且a在b之前发生,则a->b为真。
(2)如果a是一个进程发送消息的事件,而b为另一个进程接收这个消息的事件,则a->b也为真。消息不可能在发送之前就被接收,也不能在发送的同时被接收。

算法实现:
1. 每个进程Pi维护一个局部计数器Ci;
2. 在执行一个事件之前(如在网络上发送一个消息,传送一个消息给应用程序,或者其他内部事件),进程Pi执行Ci=Ci+1;
3. 当进程Pi发送一个消息m给Pj时,在执行2步骤后,把m的时间戳ts(m)设置为Ci,即ts(m)=Ci;
4. 在接收消息m时,进程Pj调整自己的局部计数器为Cj=max{Cj ,ts(m)};

如果实现两个事件不会完全同时发送?
为了实现这个目标,我们可以将事件发生所在的进程号附加在逻辑时间的低位后,并用小数点分开。例如,进程Pi中的事件发生在时刻40,那么就记为:40.i

逻辑时钟的应用(全序多播)

我们以最熟悉的转账场景开始,引出我们的问题,如果用逻辑时钟解决全序多播。

如果一位北京的客户想往旧金山的账户存进100美元,且当前他账户上有1000美元。与此同时,北京的银行职员要向该账户加进1%的利息。此数据库的两个副本都应该执行这两次更新操作。但是,由于网络延迟,这两次更新可能以相反的顺序到达。
如何解决:
发送进程把上述两个信息放到队列中。接收进程收到一个消息后,将它放进一个本地队列中,并根据它的时间戳进行排序。然后接收者向发送者发送一个确认信息。等到所有的信息都确认后,才把队列中的消息进行提交。

向量时钟

前面介绍的逻辑时钟不能确定事件之间的因果关系。即C(a) < C(b),不能代表事件a发送在事件b之前。
为了捕获事件之间的因果关系。Lamport提出了向量时钟。
向量时钟算法:

  1. 每个进程Pi维护一个向量VCi来完成。
    VCi具有以下性质:
    VC[i]是目前为止进程Pi发生的事件的数量。
    如果VCi[j]=K,那么进程Pi知道Pj中已经发生了k个事件。因此,Pi知道Pj的逻辑时间。
  2. 在执行一个事件之前(如在网络上发送一个消息,传送一个消息给应用程序,或者其他内部事件),Pi执行VCi[i] = VCi[i] + 1;
  3. 当进程Pi发送一个消息m给Pj时,在执行2步骤后,把m的时间戳ts(m)设置为等于VCi(设置一个向量);
  4. 在接收消息m时,进程Pj通过为每个k设置VCj[k] = max{VCj[k],ts(m)[k]}来调整自己的向量。

举个例子:
数据库副本复制,假如有三个数据库副本A,B,C。

  1. 初始时,A,B,C的三个初始向量为A=[0,0,0],B=[0,0,0],C=[0,0,0];
  2. 在数据库A上执行更新后变为A=[1,0,0],然后传播到B,C。B,C变为B=[1,0,0],C=[1,0,0];
  3. 在数据库B上执行更新后变为B=[1,1,0],然后传播到A,C。A,C变为A=[1,1,0],C=[1,1,0]
    等。

分布式中多进程之间的并发和协作算法

集中式算法

是仿照单处理系统中的方法,选择一个进程作为协作者。无论何时一个进程要访问共享资源,它都要向协作者发送一个请求信息,说明它想要访问哪个资源并请求准许。如果当前没有其他进程访问资源,协作者就发送准许的应答信息。

这里写图片描述

非集中式算法

只有单个的协作者往往是一种较差的方法。会存在单节点故障问题。
算法实现如下:

  1. 每个副本被复制了n
  2. 每个副本有其自身的协作者用于访问控制。
  3. 只要某个进程要访问资源,它只需从m>n/2个协作者获得多数投票即可。
  4. 当某个协作者没有获得访问某个资源的许可时,它将告诉请求者。
  5. 如果某个资源的访问被拒绝,那么它将在一个随机选择的时间后再进行下一次尝试。

算法缺点:

  1. 假设某个协作者崩溃,能快速的恢复,但会忘记奔溃前的所有投票。其风险是,重置将使得协作者忘记它前面已授权某进程访问资源的许可。因此,在其恢复后,可能错误的把该许可有赋给了另外一个进程。
  2. 如果很多节点要访问同一资源,将证明其实用性大大降低。
分布式算法

算法实现如下:

  1. 当一个进程要访问共享资源时,它构造一个消息,其中包括它要访问的资源名,进程号和当前(逻辑)时间。然后,它将该消息发送给所有其他的进程,理论上包括自己。
  2. 当一个进程接收到来自另一个进程的请求信息时,它根据自己与消息中的资源相关的状态来决定它要采取的动作。可以分为三种情况:
    (1):若接收者没有访问资源,而且也不想访问它,就向发送者发送一个OK消息。
    (2):若接收者已获得对资源的访问,那么它就不进行回答,而是将该请求放入队列。
    (3):如果接收者想访问资源但尚未访问时,它将收到的消息的时间戳与包含在它发送给其他进程的消息中的时间戳进行比较。时间戳最早的那个进程获胜。
    (4):发送许可请求后,进程进行等待,直到其他所有进程都给予了许可消息为之。一旦得到所有进程的许可,它就可以继续了。当它完成后,它向其队列中的所有进程发送OK消息,并从队列中删除。

该算法的优缺点:
该算法最大的优点是不存在单点故障。
缺点:单个故障被n个故障点取代。如果任何一个进程崩溃,它就不能回答请求。这个算法比前面的集中式算法糟糕n倍,同时要求有更多的网络流量。
缺点2:要么必须使用多播通信原语,要么每个进程都必须自己维护组成员的列表,该列表中包括进入组的进程、离开组的进程以及崩溃的进程。该方法适用于进程数目较少并且从不改变组成员的情况。

该算法的变体:
当一个进程从大多数进程获得许可时(而不需要获得所有进程的许可),它就可以获得访问许可。

令牌环算法

是一个总线式的网络,进程没有固定的顺序。在软件中,可以构造一个逻辑环,如下图所示:
这里写图片描述
算法实现:

  1. 当环初始化时,进程0得到一个令牌。该令牌绕着环运行,用点对点的方式把该令牌从进程K传到进程K+1。
  2. 进程从它邻近的进程得到令牌后,检查自己是否需要访问资源。
  3. 如果要,那么它就继续,完成它要做的工作,然后释放资源。
  4. 在该进程完成后,它岩着环继续传递令牌。
  5. 不准许进程在释放资源后,使用同一个令牌立即再次访问资源。
  6. 如果一个进程得到了邻近进程传来的令牌,但是它并相访问资源,那么它就把令牌沿环往下传递。

缺点:如果令牌丢了,那么它必须重新生成令牌。实际上,检测令牌丢失是很困难的。
如果进程崩溃,该算法也比较麻烦。

总结:在容错系统中,这些算法都不适用。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值