• paxos算法—今生


    Paxos

    定义2.1  票:即弱化形式的锁。它具备下面几个性质:

    • 可重新发布:服务器可以重新发布新票,即使前面发布的票没有释放。
    • 票可以过期:客户端用一张票来给服务器发送命令请求时,只有当这张票是最新的票才会被服务器接受。

    从票的性质中我们可以得出如下结论:

    • 客户端崩溃导致死锁的问题得到解决,因为服务器可以发布新票,从而不影响其他客户端。
    • 票可以避免死锁的问题,那么如何实现票,可以使用计数器来实现,客户端向服务器获取票的请求时,我们给计算器加1. 当客户端下次再拿服务器端分配的票时发送命令请求,服务器端可以根据该票与服务器端的票(计数器)比对来判断其是否过期,

    算法2.1   朴素的基于票的协议。

      阶段1

    1: 客户端向所有的服务器请求一张票

      阶段2

    2:  if 收到过半数服务器的回复  then

    3:        客户端将获得的票和命令一起发送每个服务器

    4:      服务器检查票的状态,如果票仍然有效,则存储命令并给客户端一个正反馈信息

    5:else

    6:         客户端等待,并重新进入阶段1

    7:    end if

        阶段3

    8:    if 客户端从过半数服务器处得到了正反馈  then

    9:              客户端告诉所有的服务器执行之前存储的命令

    10:   else

    11:          客户端等待,然后重新进入阶段1

    12:   end if 

    该算法是有问题的:

    • 假设客户端  u1 是第一个获得大多数服务器正反馈的客户端。但是u1很慢,在告知所有服务器执行先前存储的命令(c1)(算法第9行命令)之前,这时u2更新了部分服务器的票以及存储了c2命令,这时,执行第9行命令时会导致数据不一致的状态,部分服务器执行了命令c1,部分服务器执行了命令c2。
    • 如何解决以上的问题呢?如果在阶段1中服务器不但发布票还发布服务器存储的命令,当u2更新票时,发现服务器端已经存储了命令c1,这时,客户端u2可以不要求服务器存储命令c2,而是继续存储命令c1,这样两个客户端都尝试执行相同的命令c1,谁先谁后则不在重要。
    • 其次不同的服务器可能存放不同的命令。在阶段1中。客户端需要支持哪一个命令?1.对于获得大多数服务器端都支持的命令,则支持改命令,否则,选择存储票据最新的命令。票可以使用计数器变量来代替,最新的票,则计数器值最大。
    • 每个服务端都自己生产票号的话,则最新的票号不一定是最大的。服务器端的票号会存在重复的情况。如果由客户端自己来生成票号,这个问题可以得到解决。
    • 我们需要全局一致的票号,因此不能由每个服务器自己维护一个本地的计数器来产生票号。一个巧妙的办法是让客户端自己来生成票号t,然后向所有的服务器请求编号为t的票。服务器在收到请求后,先将t和它本地的计数器进行比较,只有t大于本地的计数器时,服务器才会发布票(编号为t),同时将其本地计数器的值更新为t。这样就可以得到全局一致的产生票号的方法。这就是下面paxos算法所使用的方案。

    算法 2.2  Paxos

    客户端(提案者)                                                                                    服务器(接收者)

     初始化………………………………………………………………………………………………………………………………………………………………

      c ——等待执行的命令                                                                                T(max) = 0  —— 当前已发布的最大票号

      t = 0  —— 当前尝试的票号                                                                         C = NULL   ——  当前存储的命令

                                                                                                                  T(store) = 0  ——  用来存储命令C的票

     阶段1……………………………………………………………………………………………………………………………………………………………………

     1:t = t + 1

     2: 向所有服务器发消息,请求得到编号为t的票

                                                                                                                    3:  if t > T(max)   then 

                                                                                                                    4:         T(max) = t

                                                                                                                    5:          回复ok(T(store),C)

                                                                                                                    6: endif

    阶段2………………………………………………………………………………………………………………

     7: if 过半服务器回复ok  then

     8:     选择T(store)值最大的(T(store),C)

     9:     if  T(store) > 0  then

    10:             c = C

    11:    endif

    12:    向这些回复了 ok的服务器发送消息:propose(t,c)

    13:    endif

                                                                                                                     14:  if  t = T(max).   then

                                                                                 15:         C = c

                                                             16:         T(store) = t

                                                             17:          回复:success

                                                             18:  endif

    阶段3 ………………………………………………………………………………………………………………

     19:  if  过半服务器回复  success  then 

     20:     向每个服务器发送消息:execute(c)

     21: endif 

    • 与前面算法不同的是,这个算法没有明确客户端从哪个位置可以跳转到阶段1并开始新的尝试。实际上客户端可以在算法的任何位置取消当前尝试并开始新的一轮的尝试。
    • 在阶段1 与阶段2 中如果票已经过期,可以让服务器发送负的反馈,这样可以提高性能,不必等到过半服务器发送正反馈超时而重新尝试。
    • 连续两次尝试之间的等待时间可以随机函数确定,可以缓和不同结点之间的竞争。

     

  • 相关阅读:
    HDU 5313 bitset优化背包
    bzoj 2595 斯坦纳树
    COJ 1287 求匹配串在模式串中出现的次数
    HDU 5381 The sum of gcd
    POJ 1739
    HDU 3377 插头dp
    HDU 1693 二进制表示的简单插头dp
    HDU 5353
    URAL 1519 基础插头DP
    UVA 10294 等价类计数
  • 原文地址:https://www.cnblogs.com/justinli/p/paxos.html
Copyright © 2020-2023  润新知