Paxos -- 介绍

Paxos 的理解困境

 

1 Paxos究竟在解决什么问题?

2 Paxos如何在分布式存储系统中应用?

3 Paxos算法的核心思想是什么

   第一阶段在做什么

   第二阶段在做什么

 

Paxos 用来确定一个不可变量的取值

1、取值可以是任何二进制数据

2、一旦确定将不再更改,并且可以被获取到(不可变性、可读性)

 

在分布式存储系统中应用Paxos

1、 数据本身可变,采用多副本进行存储

2、 多副本的更行操作序列[Op1,Op2,…,Opn]是相同的,不变的

3、 用Paxos依次来确定不可变量Opi的取值(即第i个操作是神什么)

4、 每次确定完Opi之后,让各个数据副本执行Opi,依次类推。

 

Google的Chubby、Megastore 和Spanner都采用了Paxos来对数据副本的根性序列达成一致

 

Paxos 希望解决的一直性问题

设计一个系统,来存储名称为var的变量

1、 系统内部由多个Acceptor组成,负责存储和管理var变量。

2、 外部有多个proposer机器任意并发调用API,想系统提交不同的var取值,var的取值可以是任意二进制数据

3、 系统对外的API库接口为:propose(var,V)=> <ok,f> or <error>

系统需要保证var的取值满足一致性

1、 如果var的取值没有确定,则var的取值为null

2、 一旦var的取值被确定,则不可以被更改。并且可以一直获取到这个值

系统需要满足容错特性

1、 可以容忍任意propose机器出现故障

2、 可以容忍少数Accptor故障(半数一下)

 

暂时不考虑 网络分化 和 acceptor故障丢去var的信息。

 

确定一个不可变变量—难点

1、 管理多个Proposer的并发执行

2、 保证var变量的不可变性

3、 容忍任意Proposer机器故障

4、 容忍半数以下Acceptor机器故障

 

确定一个不可变量变量的取值----方案1

1、 先考虑系统由单个Acceptor组成。通过类似互斥锁机制,来管理并发的proposer运行。

2、 Proposer首先向Acceptor申请Acceptor的互斥访问权,然后才能请求Acceptor接受自己的取值。

3、 Acceptor给Proposer发放互斥访问权,谁申请到互斥访问权,就接收到谁提交的取值。

4、 让Proposer按照获取互斥访问权的顺序依次访问Acceptor

5、 一旦Acceptor接受了某个Proposer的取值,则认为var取值被确定,其他Proposer不再更改

 

基于互斥访问权的Acceptor的实现

1、 Acceptor保存变量var和一个互斥锁lock

2、 Acceptor::pareprare():

加互斥锁,给予var的互斥访问权,并返回var当前的取值f

3、 Acceptor::release():

解互斥锁,收回var的互斥访问权

4、 Acceptor::accept(var,V):

如果已经加锁,并且var没有取值,则设置var为V。并且释放锁

Propose(var,V)的两阶段实现

1、 第一阶段:通过Acceptor::prepare获取互斥访问权和当前var的取值,如果不能返回<error>(锁被别人占用)

2、 第二阶段:根据当前var的取值f,选择执行

如果f为null,则通过Acceptor::accept(var,V)提交数据V

如果f不为空,则通过Acceptor::release()释放访问权,返回<ok,f>

 

通过Acceptor互斥访问权让Proposer序列运行,可以简单的实现var取值的一致性

Proposer在释放互斥访问权之前发生故障,会导致系统陷入死锁

       不能容忍任意Proposer机器故障

 

 

确定一个不可变变量的取值----方案2

引入抢占式访问权

1、 Acceptor可以让某个Proposer获取到的访问权失败,不再接收它的访问,之后,可以将访问权发给其他Proposer,让其他Proposer访问Acceptor

2、 Proposer向Acceptor申请访问权时指定编号epoch(越大的epoch越新),获取到访问权之后,才能向Acceptor提交取值。

3、 Acceptor采用喜新还旧的原则

一旦收到更大的新epoch的申请,马上让旧epoch的访问权失败,不再接受他们提交的取值。

然后给新epoch发放访问权,只接收新epoch提交的取值

4、 新epoch可以抢占旧epoch,让旧epoch的访问权失败,旧epoch的Proposer将无法运行,新epoch的Proposer将开始运行

5、 为了保持一致性,不同epoch的Proposer之间采用“后者认同前者”的原则

5.1 在肯定旧epoch无法生成确定性取值时,新的epoch会提交自己的value,不会冲突

5.2一旦旧epoch形成确定性取值,新的epoch可定可以获取到此值,并且会认同此取值,不会破坏

 

基于抢占式访问权的Acceptor的实现

1、 Acceptor保存的状态

当前var的取值<accepted_epoch, accepted_value>

最新发放访问权的epoch(lasted_prepared_epoch)

2、Acceptor::preprare(epoch):

       只接收比lasted_prepared_epoch更大的epoch ,并给予访问权,记录lasted_prepares_epoch=epoch

3、 Acceptor::accept(var ,prepared_epoch, V ):

验证lasted_prepared_epoch == prepared_epoch ,并设置var的取值<accepted_epoch,accepted_value> = <prepared_epoch,v>.

 

Proposer(var , V)的两个阶段实现

      第一阶段:获取epoch 轮次的访问权和当前var的取值

       简单选取当前世界戳为epoch,通Acceptor::prepare(epoch),获取epoch轮次的访问权和当前var的取值

       如果不能获取,返回<error>

第二阶段:采用“后者认同前者”的原则选定取值,进行提交。

       1、如果var的取值为空,则可定当前没有确定性取值,则通过Acceptor::accept(var, epoch , V)提交数据V,成功后返回<ok,V>

       如果Acceptor失败,返回<error>(被epoch抢占或者Acceptor故障)

       2.、如果var取值存在,则此值肯定是确定性取值,此时认同它不再更改,直接返回<ok, epoch_old , accepted_value>

 

总结

基于抢占式访问权的核心思想:

       让Proposer将按照epoch递增的顺讯抢占式的依次运行,后者认同前者。

可以避免proposer机器故障带来的死锁问题,并且可以var取值的一致性。

但是还得引入多Acceptor

单机模块Acceptor是故障导致整个系统yuanji ,无法提供服务

 

关于方案1

       如何控制proposer的并发运行?

       为何可以保证一致性?

       为什么会有死锁问题?

关于方案2

       如何解决方案1的死锁问题?

       在什么情况下,Proposer可以将var的取值确定为自己提供的取值?

 

抢占式访问权机制的运行过程


图一


图二(#1表示P1获取了访问权)


图3(现在是P2抢占获得了访问权,而P1保存着过期的访问权,此时Acceptor里面的lasted_prepared_epoch 比P1的大)


图4(P2成功设置了V2)


图5(P1的访问权已经失效了,所以Acceptor(#1,V1)失败)


图6(P3prepare(#3)成功,但是会返回<ok.#2,V2>,因为var已经被设置了,起到了一致性作用,所以不会在更改var的值)

 

 

 

Summary :

基于抢占式访问权的思想

       让Proposer将按照epoch递增的顺序抢占式的依次运行,后者会认同前者。

可以避免Proposer机器故障带来的死锁问题。并且还可以保证var取值的一致性

 

但是还需要引入多Acceptor

       单机模式Acceptor是故障导致整个系统down 机 ,无法提供服务

 

思考题--- 关于方案1和方案2

Problem:

关于方案1 :

       如何控制Proposer的并发运行?

       为何可以保证一致性?

       为什么会有死锁问题?

关于方案2

       如何解决方案1的死锁问题

       在什么情况下,Proposer可以将var的取值确定为自己提供的取值?

       如何保证新epoch不会破坏已经达成的确定性取值?

 

 

确定一个不可变变量的取值-----Paxos

1、Paxos在方案2的基础上引入多个Acceptor

       Acceptor的实现保持不变,仍采用“喜新厌旧”的原则运行。

2、Paxos采用“少数服从多数”的思路

3、一旦某epoch的取值f被半数以上Acceptor接受,则认为此var取值被确定为f,不再更改

 

Paxos的运行步骤:

1、 Proposer(var , V )第一阶段:选定epoch,获取epoch访问权限和对应的var取值

获取半数以上aceeptor的访问权和对应的一组var取值

2、 Proposer(var , V ) 第二阶段:采用“后者认同前者”的原则执行

在肯定旧epoch无法生成确定性取值时,新的epoch会提交自己的取值,不会冲突。

一旦旧epoch 形成确定性取值,新的epoch肯定可以获取到此取值,并且会认同此取值,不会破坏

2.1、如果获取的var取值为空,则旧epoch无法形成确定性取值,此时努力使<epoch,V>成为确定性取值。

向epoch对应的所有Acceptor提交<.epoch,V>.

如果收到半数以上成功,则返回<ok,V>

否则,则返回<error>(被新epoch抢占或者Acceptor故障)

2.2、如果var的取值存在,认同最大accepted_epoch 对应的取值,努力使<epoch,f>成为确定性取值

如果f出现半数以上,则说明f已经是确定性取值,直接返回<ok,f>

否者,向epoch对应的所有Acceptor提交取值<epoch,f>

 

图2-1(P1获取到3个访问权)



图2-2(P1向Acceptor1提交var取值,已经成功返回,接着向Acceptor2,3提交var取值,但是在此之前P2抢占式访问)


图2-3(P2抢到Acceptor1,2的访问权,Acceptor1返回被P1设置的V1取值,而Acceptor2还没有确定性取值,所以返回null)


图2-4

记住:确定值F占半数以上,成功请求访问权要超过半数,所以请求访问权如果成功,至少会包含一个确定值F(除非var为nil),然后求最大的版本号对应的F值

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值