zoukankan      html  css  js  c++  java
  • 分布式共识算法 (二) Paxos算法

     系列目录

    分布式共识算法 (一) 背景

    分布式共识算法 (二) Paxos算法

    分布式共识算法 (三) Raft算法

    分布式共识算法 (四) BTF算法

     一、背景

    1.1 命名

    Paxos,最早是Leslie Lamport 用Paxos岛的故事模型进行描述,而得以命名。这位大神原来是学数学的,最终变成了计算机科学家,在2013年获得图灵奖...附上美照:

    1.2 Paxos问题

    Paxos问题是指分布式的系统中存在故障(crash fault),但不存在恶意(corrupt)节点的场景(即能消息丢失/重复,但无错误消息)下的共识达成问题。

    1.3 Paxos协议

    Paxos 协议是一个解决分布式系统中,多个节点之间就某个值(提案)达成一致(决议)的通信协议

    1990年Leslie Lamport在论文《The Part-time Parliament》中提出Paxos共识算法,在工程角度实现了一种最大保障分布式系统一致性的机制。Paxos算法被广泛应用在Chubby、ZooKeeper中。

    Paxos wiki:Paxos (computer science)

    二、Paxos算法

    2.1 角色(核心就3个角色)

    Client:客户端,发起请求并等待返回。
    Proposer案者):处理客户端请求,将客户端的请求发送到集群中,以便决定这个值是否可以被批准。
    Acceptor(接受者):负责处理接收到的提议,他们的回复就是一次投票。会存储一些状态来决定是否接收一个值。
    Learner(学习者):当有同一个value的协议被超过一半的Acceptor采纳并发送消息给Learner时,Learner采纳该协议值。
    Leader:一个特殊的Proposer。

    2.2 Basic-Paxos算法

    核心实现Paxos Instance主要包括两个阶段:

    准备阶段(prepare phase)和提议阶段(accept phase)。细化为4个小阶段,wiki上是这样描述的:

    简单来说,Basic Paxos 是一个经典两阶段提交(2PC)

    第一阶段

    • 1a prepare 准备: proposer向acceptors提出一个协议,这里的协议就是期望的“一致性内容”
    • 1a promise 承诺: acceptor承诺只接收最大协议号的协议(包括prepare和accept),并拒绝比当前协议号N小的协议,回复proposer之前接收的所有协议值。如果当前协议号N比之前都小,那么回复拒绝。

    第二阶段

    • 2a Accept Request 发起“accept”请求:proposer收到acceptor反馈的足够的承诺后,给协议设最大值,如果没回复,随便设置一个值。发送"accept"请求给选定值的acceptors.
    • 2b Accepted: acceptor接受协议(该acceptor之前没有承诺过大于该协议号的协议),并通知给proposer和learner.

      配上wiki流程图如下:

    其中prepare阶段的作用,如下图所示:

    1.S1首先发起accept(1,red),并在S1,S2和S3达成多数派,red在S1,S2,S3上持久化
    2.随 后S5发起accept(5,blue),在S3,S4和S5达成多数派,blue在S3,S4和S5持久化
    4.最后的结果是,S1和S2的值是red,而S4和S5的值是blue,s3存在异议,red覆盖了blue?

    解决方案:

    • 1.将提议进行排序,可以为每个提议赋予一个唯一的ID,规定这个ID越大越新,很明显(5,blue)和(1,red),5比1大,所以保留blue
    • 2.采用两阶段方法,拒绝旧提议

    2.3 Muti-Paxos算法

    很多文章有误解说Muti-Paxos是一阶段提交,那是仅限于leader稳定时。刚选出来一个新的leader时,依然是二阶段提交如下图:

     如果leader稳定不需要prepare和promise步骤,如下图(图中Proposer就是一个Leader):

    Multi Paxos中leader用于避免活锁(例如1个leader,4个Proposer,2个提议A,2个提议B不能达成一致,导致活锁),但leader的存在会带来其他问题,一是如何选举和保持唯一leader(虽然无leader或多leader不影响一致性,但影响决议进程progress),二是充当leader的节点会承担更多压力,如何均衡节点的负载。Mencius[1]提出节点轮流担任leader,以达到均衡负载的目的;租约(lease)可以帮助实现唯一leader,但leader故障情况下可导致服务短期不可用。

    2.4 Muti-Paxos在google chubby中的应用

    Google Chubby是一个高可用分布式锁服务,被设计成一个需要访问中心化节点的分布式锁服务。本文只分析chubby服务端的实现。

     Chubby服务端的基本架构大致分为三层

      ① 最底层是容错日志系统(Fault-Tolerant Log),通过Paxos算法能够保证集群所有机器上的日志完全一致,同时具备较好的容错性。

      ② 日志层之上是Key-Value类型的容错数据库(Fault-Tolerant DB),其通过下层的日志来保证一致性和容错性。

      ③ 存储层之上的就是Chubby对外提供的分布式锁服务和小文件存储服务。

     

     Paxos算法用于保证集群内各个副本节点的日志能够保持一致,Chubby事务日志(Transaction Log)中的每一个Value对应Paxos算法中的一个Instance(对应Proposer),由于Chubby需要对外提供不断的服务,因此事务日志会无限增长,于是在整个Chubby运行过程中,会存在多个Paxos Instance,同时,Chubby会为每个Paxos Instance都按序分配一个全局唯一的Instance编号,并将其顺序写入到事务日志中去。

      在Paxos中,每一个Paxos Instance都需要进行一轮或多轮的Prepare->Promise->Propose->Accept这样完整的二阶段请求过程来完成对一个提议值的选定,为了保证正确性的前提下尽可能地提高算法运行性能,可以让多个Instance共用一套序号分配机制,并将Prepare->Promise合并为一个阶段。具体做法如下:

      ① 当某个副本节点通过选举成为Master后,就会使用新分配的编号N来广播一个Prepare消息,该Prepare消息会被所有未达成一致的Instance和目前还未开始的Instance共用。

      ② 当Acceptor接收到Prepare消息后,必须对多个Instance同时做出回应,这通常可以通过将反馈信息封装在一个数据包中来实现,假设最多允许K个Instance同时进行提议值的选定,那么:

      -当前之多存在K个未达成一致的Instance,将这些未决的Instance各自最后接受的提议值封装进一个数据包,并作为Promise消息返回。

      -同时,判断N是否大于当前Acceptor的highestPromisedNum值(当前已经接受的最大的提议编号值),如果大于,那么就标记这些未决Instance和所有未来的Instance的highestPromisedNum的值为N,这样,这些未决Instance和所有未来Instance都不能再接受任何编号小于N的提议。

      ③ Master对所有未决Instance和所有未来Instance分别执行Propose->Accept阶段的处理,如果Master能够一直稳定运行的话,那么在接下来的算法运行过程中,就不再需要进行Prepare->Promise处理了。但是,一旦Master发现Acceptor返回了一个Reject消息,说明集群中存在另一个Master并且试图使用更大的提议编号发送了Prepare消息,此时,当前Master就需要重新分配新的提议编号并再次进行Prepare->Promise阶段的处理。

      可见chubby就是一个典型的Muti-Paxos算法应用,在Master稳定运行的情况下,只需要使用同一个编号来依次执行每一个Instance的Promise->Accept阶段处理。

      

    三、总结

    Paxos算法的变种还有很多Cheap PaxosFast Paxos等等,本文介绍了使用最广的Muti-Paxos算法。希望能够带给大家一点分布式一致性算法的入门灵感和思想。

    ====================

    参考:

    1.paxos的wiki:Paxos (computer science)

    2.csdn博客:一步一步理解Paxos算法

    3.书:《从Paxos到Zookeeper》

    4.论文:《Time-Clocks-and-the-Ordering-of-Events-in-a-Distributed-System》

    5.书:《区块链 原理、设计与应用》

  • 相关阅读:
    C++内存机制中内存溢出、内存泄露、内存越界和栈溢出的区别和联系
    ArrayList、Vector、HashMap、HashTable、HashSet的默认初始容量、加载因子、扩容增量
    C++ 智能指针 auto_ptr 和 shared_ptr
    Java初始和环境搭建(一)
    Spring_01
    Linux中常用命令
    linux_Ubuntu项目运行环境搭建
    Nginx_Ubuntu
    idea运行时 Process finished with exit code -1073741819 (0xC0000005)
    MySQL_基础
  • 原文地址:https://www.cnblogs.com/dennyzhangdd/p/6781688.html
Copyright © 2011-2022 走看看