2021-06-01

一、paxos算法

 

1、Basic Paxos 算法

 

描述的是多节点之间如何就某个值(提案 Value)达成共识。采用两阶段提交的分布式事物。

 

在 Basic Paxos 中,有提议者(Proposer)、接受者(Acceptor)、学习者(Learner)三种角色

 

  • 提议者(Proposer)提议一个值,用于投票表决。粗略的,可以把访问集群的客户端也当做提议者。但在绝大多数场景中,集群中收到客户端请求的节点,才是提议者。二阶段提交的发起者
  • 接受者(Acceptor):对每个提议的值进行投票,并存储接受的值。一般来说,集群中的所有节点都在扮演接受者的角色,参与共识协商,并接受和存储数据。
  • 学习者(Learner):被告知投票的结果,接受达成共识的值,存储保存,不参与投票的过程。一般来说,学习者是数据备份节点,比如“Master-Slave”模型中的 Slave,被动地接受数据,容灾备份。提高集群的高可用性。

 

提议者和接受者的关系如下。提议者和接受者的角色不是固定的,任何节点在某个时刻都有可能是提议者,也有可能是接受者。

 

下面讨论二阶段提交的两个阶段。

 

两个阶段都有相应的请求,分别叫“准备请求”和“接受请求”(注意这里的“准备”和“请求”不是动词,而是形容词),对应的响应分别叫做“准备响应”和“接受响应”。

 

1.1、准备(Prepare)阶段

 

这个阶段的目的,自己的理解是就节点间需要就表决的对象达成一致,这个需要表决的对象在PAXOS算法中被称为提案,每个提案有一个唯一标识,被称为编号。

 

在PAXOS集群中,是有时序概念的,PAXOS集群的世界发生的事情都有一个编号,这个标号是递增的,象征PAXOS宇宙中滚滚向前的历史的车轮,集群的节点只会处理最新编号提案,对过期的提案,会被抛弃。这大概是因为集群会发生分区,每个节点(主要是提议者)的时钟也会不准,提案编号就像一个节拍器,所有节点都按照它的指示统一行动。

 

所以在准备阶段,提议者在准备请求时,只需要携带提案编号就可以了,并不需要指定提案的值。每个接受者一旦接受了一个编号为N的提案,那么以后如果收到了编号小于N的提案就不会通过,也不会对提议者做出响应

 

提议者会对收集到的大部分(注意,并不是全部)对提案的响应中,选一个最大的编号作为自己提案的编号,或者说是给选定的提案编号配上提案内容。

 

所以,在准备阶段中,一方面,接受者会决定一个自己可以通过的提案编号(大于等于目前收到的最大的提案编号)和一个自己可以接受的提案编号(大于目前收到的最大的提案编号);另一方面,提议者也会从收到的大部分响应中,选一个最大的,作为自己的提案编号(但这个编号在接受阶段可能会被接受者拒绝)。

 

如上图,提议者1的编号为1的请求被节点A\B准备响应,但由于节点C先收到了编号为5请求,所以节点C不会响应提议者1的请求,而提议者2的编号为5的请求会被节点A\B和C先后响应。

 

准备阶段结束后,提议者知道自己该使用的提案编号和提案的内容:

  • 提议者1可以使用提案编号1,提案内容可以自己决定(应为准备响应中没有接受者之前收到的提案值);
  • 提议者2可以使用提案编号5,提案内容可以自己决定(应为准备响应中没有接受者之前收到的提案值)。

另一方面,接受者知道自己可以通过的最小的提案编号

  • 节点A\B只会通过大于等于编号为5的提案;
  • 节点C只会通过大于等于编号为5的提案。

 

1.2、接受(Accept)阶段

 

在接受阶段开始,如准备阶段最后所说:

 

  • 提议者1可以使用提案编号1,提案内容可以自己决定(应为准备响应中没有接受者之前收到的提案值);
  • 提议者2可以使用提案编号5,提案内容可以自己决定(应为准备响应中没有接受者之前收到的提案值)。

 

有下图的状态

提议者1根据大多数准备响应(节点A\B)中提案编号最大的提案值设置接受请求中的值,因为准备响应的提案值都是空的,所以可以使用自己的提案值3发送接受请求[1, 3]。

同理,提议者2就把7作为自己的提议值发送接受请求[5, 7].

 

当接受请求到达接受者时,如准备阶段最后所说:

  • 节点A\B只会通过大于等于编号为5的提案;
  • 节点C只会通过大于等于编号为5的提案。

所以编号为1的提案会被拒绝,编号为5的提案会被接受,如下图所示

 

上面的过程感觉提议者不同提案的编号并没有一个“主题”,以表明大家在就什么进行投票,比如就设置x的值进行投票。

 

总结:Basic Paxos 是通过二阶段提交来达成共识的。在第一阶段,也就是准备阶段,接收到大多数准备响应的提议者,才能发起接受请求进入第二阶段(也就是接受阶段):

 

2、Multi-Paxos

 

Basic Paxos 只能就单个值(Value)达成共识,一旦遇到为一系列的值实现共识的时候,它就不管用了,此时需要Multi-Paxos算法。但原始论文中缺少算法过程的细节和编程所必须的细节(比如缺少选举领导者的细节),所以兰伯特提到的 Multi-Paxos 是一种思想,不是算法。而 Multi-Paxos 算法是一个统称,它是指基于 Multi-Paxos 思想,通过多个 Basic Paxos 实例实现一系列值的共识的算法(比如 Chubby 的 Multi-Paxos 实现、Raft 算法等)。

 

Multi-Paxos是通过多次执行Basic Paxos 实例,来实现一系列值的共识,这时会带来两个问题:

  • 提议者必须得到大多数接受者的响应才可以进入第二阶段,如果提议者的提案很多,那么提议者很可能得不到大多数接受者的响应。类似于提案分裂;
  • 两阶段需要多次的网络通讯,往返消息多、耗性能、延迟大。

 

2.1、架构上的优化

 

从架构的角度来考虑,Basic Paxos的多个节点组成的网络拓扑每个节点间都存在链接,不是一个单向的分层架构,所以可以引入一个领导者来进行分层,如下

只有领导者才可以发起提议。有了领导者,就必须有一个选主的过程,这个选主算法都是实现paxos算法时必须有的。

 

相当于从对等式结构变成了中心式架构。但LEADER节点的选举还是由对等式架构的节点通过Basic Paxos进行的。

 

在《分布式技术原理与算法解析》中提到的选主算法有如下几种:

 

 

  • Zookeeper使用ZAB(ZooKeeperAtomicBroadcast)算法。相较于Raft算法的投票机制,ZAB算法增加了通过节点ID和数据ID作为参考进行选主,节点ID和数据ID越大,表示数据越新,优先成为主。相比较于Raft算法,ZAB算法尽可能保证数据的最新性。所以,ZAB算法可以说是对Raft算法的改进。选举过程中,在某一轮中如果有一个serverID最大的节点,则会直接结束选举。
  • Google开源的Kubernetes,为了保证可靠性,通常会部署3个节点用于数据备份。这3个节点中,有一个会被选为主,其他节点作为备。Kubernetes的选主采用的是开源的etcd组件。而etcd的集群管理器etcds,是一个高可用、强一致性的服务发现存储仓库,就是采用了Raft算法来实现选主和一致性的。
  • MongoDB采用Bully算法,谁活着而且谁的节点ID大谁就是主节点。

 

2.2、减少网路通讯

 

在本笔记第一小节说过,两阶段中第一个准备阶段的目的是为了找到一个提议者和接受者都认可的提案编号。为了减少一个阶段,就必须有一个节点能保持“paxos宇宙中的时间线”,维护请求序列,知道哪个请求已经过期了,即能确定提案的编号,这样的节点也是领导者担任。

 

和重复执行 Basic Paxos 相比,Multi-Paxos 引入领导者节点之后,因为只有领导者节点一个提议者,只有它说了算,所以就不存在提案冲突。另外,当主节点处于稳定状态时,就省掉准备阶段,直接进入接受阶段,所以在很大程度上减少了往返的消息数,提升了性能,降低了延迟。

 

2.3、Chubby 的 Multi-Paxos 实现

 

这个实现就使用了上面的优化思路。此外,在 Chubby 中,为了实现强一致性,读操作也只能在主节点上执行。 也就是说,只要数据写入成功,之后所有的客户端读到的数据都是一致的(即在主从间采用了同步式数据复制技术)。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值