Paxos算法

Paxos算法

Paxos算法是一系列共识算法中的一个,其目的就是为了解决共识/一致性问题

这个Github连接中详细的列出了多种共识算法,还有一些工程实践的例子: 腾讯, Zookeeper(Handpoo下的一个分布式框架(Handoop是一个大数据分析和处理的软件平台,用Java写的,可以对大量计算机组成的集群进行海量数据的分布式计算))
算法
工程实践例子

本文主要介绍Paxos算法的背景和运用

三篇Paxos算法的文章: The Part-Time Parliament ,Paxos made simple,Fast Paxos

共识/一致性问题

假设有一组服务器保存了用户的余额,初始是100块,现在用户提交了两个订单,一个订单是消费10元,一个订单是充值50元。由于网络错误和延迟等原因,导致一部分服务器只收到了第一个订单(余额更新为90元),一部分服务器只收到了第二个订单(余额更新为150元),还有一部分服务器两个订单都接收到了(余额更新为140元),这三种保存用户余额的服务器无法就最终余额达成一致。

这就是一致性问题,即在多节点的网络中各节点就某一数据无法达成一致, 我们称解决共识问题的算法为共识算法

造成一致性问题的因素有很多:

  • 网络延迟
  • 不稳定的节点: 节点故障,断电,损坏等因素造成节点无法连入网络

总之一个分布式系统想要数据能够稳定可靠的在节点之间进行交流,就需要解决共识/一致性问题

FLP不可能定理

一般来说,一个问题都存在理论上的下限,例如对于囚徒困境问题,我们可以使用博弈论来进行分析,得出囚徒困境的最坏结果

对于一致性问题,我们也可以证明一致性问题的最差结果,即FLP定理. FLP定理由Fischer,Lynch和Patterson三人于1985年发表的论文中给出了证明,主要使用的是图论

FLP定理给出了异步分布式系统的共识问题的最差情况: 无解, 即在网络通信可靠的情况下,可扩展的异步分布式系统的共识问题是无解的, 因此不存在一个可以解决任意场景下的共识问题的算法

因此设计对任意场景下都适用的共识算法是徒劳的.但是我们可以开发针对某些特定场景下的共识算法,即在加强条件情况下的共识算法

Paxos算法

Paxos算法前提

明确一个算法的假设/前提/适用条件/使用场景才能知道该在什么情况下使用这个算法,所以先介绍Paxos算法的假设

通过前面的FLP定理可知,不存在通用的共识算法,因此==Paxos算法是针对非拜占庭场景下的共识算法==

拜占庭问题

拜占庭帝国想要进攻一个强大的敌人,为此派出了10支军队去包围这个敌人。这个敌人虽不比拜占庭帝国,但也足以抵御5支常规拜占庭军队的同时袭击。基于一些原因,这10支军队不能集合在一起单点突破,必须在分开的包围状态下同时攻击。他们任一支军队单独进攻都毫无胜算,除非有至少6支军队同时袭击才能攻下敌国。他们分散在敌国的四周,依靠通信兵相互通信来协商进攻意向及进攻时间,甚至还可以不传递消息。困扰这些将军的问题是,他们不确定通信兵中是否有叛徒,叛徒可能擅自变更自身传递的消息,即可以给其他军队带去恶意的消息。在这种状态下,拜占庭将军们能否找到一种分布式的协议来让他们能够远程协商,从而赢得战斗

简单的来说,拜占庭问题的核心是: 不可靠的通信

因此,Paxos算法的前提就是具备可靠的通信,节点间通信的可靠(消息能否送达), 和节点的安全性(节点不会被入侵而恶意攻击网络)就不是Paxos算法考虑的问题了.

Paxos算法的具体操作

Paxos算法的理论推导很麻烦, 特别绕, 但是有助于理解Paxos算法, 实际上Paxos算法的运用很简单

Paxos算法中的概念

Paxos算法是分轮次的,每一轮称为一个Paxos过程,每一轮都将会得到一个提案

Paxos算法中将网络中所有的节点分成了三种角色:

  • 提案者(Proposer)
    提案者负责提出提案,提案可以是任何需要达成共识/一致的内容, 比如一个日志,一个数据等等
    不同的提案者可以提出不同的甚至矛盾的内容,例如某个提案提议“将变量 X 设置为 1”, 另一个提案者提议“将变量 X 设置为 2”
    但对同一轮 Paxos 过程,最多只有一个提案的内容被批准
  • 接受者(Acceptor)
    接受者负责接收提案,并明确是接收还是拒绝
    只有被半数以上的接受者接收的提案才会被批准/通过
  • 学习者(Learner)
    学习者负责获取并同步最终通过/批准的提案,即明确最终的提案
    具体来说就是学习者通过读取各个提案者对这一轮各自提案的选择结果,如果某个提案被超过半数接受者通过,则学习者学习到了
    这个提案

此外对于提案还有分类:

  • 提案(Proposal) : 提案是一个由提案编号和提案值组成的键值对,即[proposalNo, proposalValue]([提案编号, 提案内容])
  • 共识(sensus) : 被半数以上的接受者接收的提案, 提案编号是最终能达成共识的关键

还有一些约束条件:

  • 提案的编号全局唯一且递增
  • 每个接受者都会记录已响应过的提案的最大编号,并且承诺不会接受比此提案号小的提案
  • 如果一个提案的v值(即提案的内容)被大多数接收者接收,那后续的所有被接受的提案中也必须包含先前被接受的提案的v值(提案由一个或多个v值和一个提案编号组成)
  • 提案者和接受者可以是同一个节点, 这有助于提案ID的增大

Paxos算法的流程

Paxos算法整体分为两步, 准备阶段(每个提案者提出自己的提案)和选举阶段(学习者确定最终的提案)

准备阶段
  1. 提案者生成全局唯一且递增的提案编号,ProposalID,并且向网路中的所有节点(接受者)发送Prepare请求
    Prepare请求不携带ProposalValue, 即不携带具体的提案内容,只有提案编号
  2. 接受者接收到提议者发来的Prepare请求后, 判断Prepare请求中的提案编号和之前已经响应的所有提案的编号大
    a. 如果大于先前所有的提案编号, 则
    a1. 在本地持久化该编号
    a2. 回复Prepare请求,并带上该接受者先前已经接受的提案中最大编号提案的提案编号和内容
    若此时还没有已Accept的提案,则返回的提案内容为空
    a3. 做出承诺: 不会接受任何小于当前更新后提案编号的提案
    b. 如果小于或等于先前所有的提案编号,则
    不回复Prepare请求或者回复Error
选举阶段
  1. 提案者发送Accept请求
    经过一段时间之后,提案者已经接收到一些接受者返回的请求,有以下三种情况:
    a. 回复数量 > 一半接受者数量, 且所有回复中的值为空, 则提案者向所有接受组合发出Accept请求,并带上自己的提案内容
    b. 回复数量 > 一半接受者数量, 且所有回复中的值不为空, 则提案者向所有接受组合发出Accept请求,并带上提议者接收到所
    有接受者的回复中最大的提案编号和对应的提案内容(把编号最大的提案的内容当做自己的提案内容)
    c. 回复数量 > 一半接受者数量, 且所有回复中的值不为空, 则尝试生成更大的ProposalID,然后结束此次提案,等待下一轮的准
    备阶段发出自己的提案
  2. 接受者应答提案者发来的Accept请求
    接受者收到Accept请求后,判断:
    a. 收到的提案编号 >= 先前最大的提案编号(一般情况下是等于),则回复提交成功,并持久化新接收到的提案编号和提案内容
    b. 收到的提案编号 < 先前最大的提案编号, 则不回复或者回复提交失败
  3. 提案者统计接受者返回的应答
    经过一段时间后,提案者收集到一些接受者回复的信息,有几种情况:
    a. 回复数量 > 一半的接受者数量, 则表示提交value成功. 此时, 可以发一个广播给所有提案者和学习者,通知它们自己的提
    提案已经被通过,并带上自己的提案内容
    b. 回复数量 <= 一半的接受者数量,则尝试生成更大的 ProposalID, 然后结束此次提案,等待下一轮的准备阶段发出自己的提

    c. 收到一条提交失败的回复, 则尝试生成更大的 ProposalID, 然后结束此次提案,等待下一轮的准备阶段发出自己的提案

Paxos算法时序图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4SMOBQDb-1608098281783)(图片/TB1lKX_gbGYBuNjy0FoXXciBFXa-932-698.png)]

Paxos算法的一些讨论

如何产生唯一的编号?

Paxos made simple中提到的是让所有的提案者都从不相交的数据集合中进行选择,例如系统有5个提案者,则可为每一个提案者分配一个标识j(0~4),则每一个提案者每次提出决议的编号可以为5*i + j(i可以用来表示提出议案的次数)

为什么在Paxos运行过程中,半数以内的接受者失效都能运行?

  1. 如果半数以内的接受者失效时还没确定最终的提案内容, 则此时, 所有的提议者实际上会发生竞争,最终会有一个提案会成功提交。再这之后,会有半过数的接受者以这个提案的内容提交成功。
  2. 如果半数以内的接受者失效时已确定最终的提案内容, 则此时, 所有提案者提交时必须以最终的提案的内容提交, 此值也可以被获取,并不再修改

如果过半数接受者失效,则最终能否产生一个提案?

不行,因为最终提案的产生要求具有半数以上的接受者同意

不过我自己的一个想法就是可以实行动态的半数接受者,即只要当前可用的接受者的半数即可(初步想法,没细想)

效时已确定最终的提案内容**, 则此时, 所有提案者提交时必须以最终的提案的内容提交, 此值也可以被获取,并不再修改

如果过半数接受者失效,则最终能否产生一个提案?

不行,因为最终提案的产生要求具有半数以上的接受者同意

不过我自己的一个想法就是可以实行动态的半数接受者,即只要当前可用的接受者的半数即可(初步想法,没细想)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值