浅谈paxos协议与zookeeper

一、介绍两篇好博客

1、zookeeper全解析–paxos作为灵魂
https://blog.csdn.net/YQlakers/article/details/72630353
2、下面这篇文章介绍paxos协议更为透彻
https://www.cnblogs.com/linbingdong/p/6253479.html

简单来说,paxos就是为了解决在一个分布式集群中,集群中的节点是如何交流沟通,来完成一个唯一确定的事情。这个例子在博客1中讲解的十分形象。这个唯一确定的事情可以是更改某个数据,可以是更新某个配置文件。
zookeeper不仅继承了paxos协议中分布式的部分,还增加了watch等机制,方便做集群的主动同步。

二、paxos协议简单理解

由简单到复杂进行讲解:

1 如果集群中只有一个处理请求的节点

集群中三个节点A,B,C,均想更改file1的数据。而涉及到更改,需要互斥,因此所有修改请求均发送至D节点进行互斥。这也是最容易想到的互斥方法。但是如果D节点宕机,集群就会陷入瘫痪。因此需要更为进一步的处理方式。

2 增加多个处理请求的节点

集群中处理请求的节点变为多个,D,E,F均可处理A,B,C的请求。
这样就带来麻烦,D节点既可以接到A的请求,也可以接到B的请求,因此对于接受请求的节点来说,一个时间范围内(纪元)只能认为一个请求是有效的。而由于最终的要求是在一个纪元内只有一个请求能够生效,因此规定只有半数以上(只有这样才能保证一个纪元内只有一个请求有效)处理节点认为某个请求生效,这个请求才真的生效。

2-1

为了实现上面的请求,我们需要在请求中加入时间戳。每个接收处理的节点只相应某个时间戳的第一个请求,举例D收到A、B的请求,时间戳均为1,收到C的请求,时间戳为0,那么D只认为A请求有效。

2-2

考虑以下场景:D、E认为A有效,F认为B有效,没有人认为C有效。这样,根据上述约定,实际上A是生效的,但是怎样把这个信息通知给F以及B和C呢?因此我们还需要一个流程:预提交流程。也就是说,B在提交F失败之后(只有F一个同意,没超过半数),还会再次提交,提交之前有个预处理过程,会给D、E、F均再次提交自己的请求,D、E由于人为A有效,会拒绝B的处理,并把A的处理结果返回给B,这样B就认怂了,经过预提交之后,正式提交的内容,就是A的处理结果,这样整个集群就统一了。或者D、E干脆不理会B的请求,B的提交就永远无法生效,那么B节点就只能靠被动学习的方式,等待集群通知。

2-3 活锁

实际上,zookeeper在使用paxos时,并没有采用2-2的方式进行proposal的提交。原因就是会有活锁的产生:
如2-2所说,所有提交由两部分组成:预提交以及提交。
假如A在预提交过程中,确认了纪元为1,准备进行提交,这时B也预提交,确认了纪元为2,当A提交时发现提交无效了,原因是B进行了预提交,acceptor那边已经把最大纪元更新为2了,这时A将纪元更新为3,这样则又会导致B也无法提交,这样循环往复,构成了活锁。

3 leader模式

为了避免2-3所述活锁的问题,zookeeper利用一个leader作为所有proposal的提交者。提交过程采用两阶段提交的方式。只有当选主的时候采用paxos一致性协议进行选主。选完主之后,就和paxos无关了。

三、paxos,zookeeper,两阶段提交,三阶段提交之间的关系

整体上看,应该是首先有两阶段提交,为了解决两阶段提交的各种问题引入了三阶段提交,但是始终无法解决一致性问题,paxos是唯一能够保证分布式一致性的协议,而zookeeper则是利用了paxos中的一致性协议,并进行了变更产生了自己的zab协议,zab协议中选leader是paxos的思想,而通过leader发出proposal,半数以上同意则是综合了paxos和两阶段提交两者的思想。

1 两阶段提交和三阶段提交的区别

首先还是介绍一片文章
https://www.cnblogs.com/AndyAo/p/8228099.html
实际上网上关于两阶段和三阶段的帖子大多一样,这里就不再重复,只说下自己的理解。
分布式事务中,分为协调者和参与者。
假设协调者为A,参与者为B、C、D

1-1两阶段提交:

阶段一:A告诉B、C、D都给自己数据减10,B、C、D把减10操作加入redolog,把加10操作放入undolog
阶段二:A收到所有回复,告诉大家可以提交,B、C、D把内存中的临时内容真正下到磁盘。
如果阶段二中,A并没有收到所有回复,那么会给所有节点发abort消息,所有节点将会执行undolog,把内存中临时内容恢复。
核心问题就集中在,假如A告诉所有人可以下盘,这时只有B收到了,C和D都没收到,然后A和B都宕机了。这时,就算C和D有了新的协调者,他们也不知道怎么处理自己内存中的数据。随意处理均会引起集群中的不一致

1-2 三阶段提交

为了解决上述问题,引入了三阶段提交。上面说了,即使C和D有了新的协调者,他们也不知道怎么处理内存的数据。实际上他们的处理方式无非两种:1、下盘,2、恢复原来。因此,三阶段提交,就是多了一个阶段,在这个阶段之前,C和D就恢复,在这个阶段之后,C和D就下盘。这个阶段就是新增加的那个阶段:precommit
阶段一:A告诉B、C、D 要进行活动了。更像是对链路可靠性的检测。
阶段二:A如果都收到回复,就执行precommit,也就是两阶段提交的阶段一。如果有一个没收到,本次事务就失败。
阶段三:A如果都收到回复,就执行commit,如果一个没有收到,就执行abort。
两阶段的问题如果在阶段二时发生,也就是说A的precommit的请求发给了B、C、D,之后A和B宕机,那么C和D直接undo就可以了。
两阶段的问题如果在阶段三时发生,也就是说A的committ的请求发给了B、C、D,之后A和B宕机,那么C和D直接commit就可以了。
为何三阶段依然无法解决一致性?因为A有可能给B发的是abort请求。而C和D选择的是commit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值