只会一点java

java持续学习者,每月一篇博客。罗列出技术栈,慢慢完善,持续学习,总有一天,你会追上甚至超越曾经的大神。
  博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

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

Posted on 2017-05-23 20:39  只会一点java  阅读(5857)  评论(2编辑  收藏  举报

 系列目录

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

分布式共识算法 (二) 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.书:《区块链 原理、设计与应用》