zookeeper读书笔记十三 zookeeper应用之实现两段提交

2PC

    2PC,二阶段提交协议,即将事务的提交过程分为两个阶段来进行处理:准备阶段和提交阶段。事务的发起者称协调者,事务的执行者称参与者。

第一阶段:提交事务阶段(投票阶段)

事务询问:协调者会询问所有的参与者结点,是否可以执行提交操作,并等待响应。
执行事务:各个参与者执行事务操作,并将Undo和Redo信息记入事务日志中。
参与者向协调者反馈事务询问的响应:如果参与者成功执行了事务操作,反馈给协调者Yes响应,否则No响应表示事物不可执行。
第二阶段:执行事务提交(执行阶段)
    协调者根据各个参与者的反馈情况来决定是否可以进行事物的提交操作,因此有两种可能:

执行:

发送提交请求:协调者向参与者发送Commit请求。
事务提交:参与者接受到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放执行期间占用的事务资源。
反馈事务提交结果:参与者在完成事务提交之后,向协调者发送Ack消息。
完成事务:协调者接受到所有参与者反馈的Ack消息后,完成事务。
中断:

发送回滚请求:协调者向所有参与者发送Rollback请求。
事务回滚:参与者接受到Rollback请求后,利用Undo信息来执行事务回滚,并释放事务资源。
反馈事务回滚结果:参与者在完成事务回滚之后,向协调者发送Ack消息。
中断事务:协调者接收到所有参与者反馈的Ack消息之后,完成中断事务。
二阶段提交优点:原理简单,实现方便

二阶段提交缺点:同步阻塞、单点问题、脑裂、太过保守

1、同步阻塞

    二阶段提交过程中,所有参与该事物操作的逻辑都处于阻塞状态。各参与者等待其他参与者响应的过程中。将无法进行其他操作。这会很影响分布式系统的性能。
2、单点问题

    协调者一旦出现问题,整个二阶段提交过程都无法进行。如果协调者是在阶段二中出现问题,那么参与者将会一直处于锁定事务资源的状态中,而无法完成事务操作。
3、脑裂(数据不一致)

    当协调者向所有参与者commit请求后,发生局部网络异常或者协调者尚未发送完commit请求之前自身发送崩溃。导致只有部分参与者收到commi请求。这部分收到请求的参与者就会进行事务提交,而没收到commit请求的参与者无法事务提交。因此造成了整个分布式系统数据不一致。
4、太过保守

     如果协调者指示参与者进行事务提交询问的过程中,参与者出现故障而导致协调者始终无法获取到所有参与者的响应信息。协调者只能依靠自身的超时机制来判断是否需要中断事务,这样做有些保守。因为二阶段提交没有设计完善的容错机制,任何一个节点的失败都会导致整个事物的失败。
 

3PC
 

    3PC,三阶段提交协议,是2PC的改进版本,即将事务的提交过程分为CanCommit、PreCommit、doCommit三个阶段来进行处理。

阶段1:CanCommit

事物询问:协调者向所有参与者发出包含事务内容的CanCommit请求,询问是否可以提交事务,并等待所有参与者响应。
各参与者向协调者反馈事物询问的响应:参与者收到CanCommit请求后,如果认为可以执行事务操作,则反馈YES并进入预备状态,否则反馈NO。
阶段2:PreCommit
    协调者根据参与者反馈来决定是否可以进行事物的PreCommit操作,有两种情况:

所有参与者均反馈YES,即执行事务预提交。
  事务预提交:(所有参与者均反馈YES时)

发送预提交请求:协调者向所有参与者发出PreCommit请求,进入准备阶段。
事物预提交:参与者收到PreCommit请求后,会执行事务操作,将Undo和Redo信息记入事务日志中(但不提交事务)。
各参与者向协调者反馈事物执行的响应:如果参与者成功执行了事物操作,那就反馈给协调者Ack响应,同时等待最终的指令:提交或者终止。
 任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务。
  中断事务:(任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈时)

发送中断请求:协调者向所有参与者发出abort请求。
中断事物:无论收到协调者发出的abort请求,或者在等待协调者请求过程中出现超时,参与者均会中断事务。
阶段3:doCommit
 
  提交事务:(所有参与者均反馈Ack响应时)

发送提交请求:如果协调者处于工作状态,并且接受所有参与者的Ack响应,那么他会从预提交转换为提交状态,并向所有参与者发出do Commit请求。
事物提交:参与者收到doCommit请求后,会正式执行事务提交操作,并完成提交之后释放整个事务期间占用的资源。
反馈事物提交结果:各参与者完成事物提交之后,向协调者反馈Ack完成的消息。
完成事务:协调者收到所有参与者反馈的Ack消息后,即完成事务提交。
  中断事务:(任何一个参与者反馈NO,或者等待超时后协调者尚无法收到所有参与者的反馈时)
发送中断请求:如果协调者处于工作状态,向所有参与者发出abort请求。

事物回滚:参与者接收到abort请求后,会使用阶段二中记录的Undo信息执行回滚操作,并在完成回滚之后释放整个事务期间占用的资源。
反馈事物回滚结果:参与者完成回滚后,各参与者向协调者反馈Ack消息。
中断事物:协调者收到所有参与者反馈的Ack消息后,完成事务中断。
三阶段提交协议的优点:相对于二阶段协议降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调者单点故障,阶段3中协调者出现问题时,参与者会继续提交事务。
 
三阶段提交协议的缺陷:脑裂问题依然存在,即在参与者收到PreCommit请求后等待最终指令,如果此时协调者无法与参与者正常通信,会导致参与者继续提交事务,造成数据不一致。 

3PC相较于2PC的优化是:

先进行一次CanCommit,确认所有的服务都是正常的。不像2PC中直接进行事务预提交,如果有服务是挂的,那么会出现协调者一直得不到这个服务的响应,最终timeout后还要回滚其它的服务的事务。

3PC中的协调者和参与者都加入了超时自动处理的机制,协调者等待超时会取消事务,参与者等待超时会自动提交事务。

 

zookeeper实现两阶段提交,假设一笔交易,网关需要调交易服务扣钱,扣钱成功后需要调库存服务减库存。那么网关就是协调者,交易服务和库存服务就是参与者。

  1. 网关在zookeeper创建父节点/app/Tx,并对/app/Tx/trade和/app/Tx/store子节点执行exist(path,true)方法,子节点创建时,网关得到通知,然后对子节点执行get(path,true)方法,设置watch。
  2. 网关调用交易服务,交易服务创建子节点/app/Tx/trade,并开始执行执行业务逻辑,如果执行成功则向子节点中写入yes,如果异常则写入no。同时对父节点/app/Tx执行get(path,true),设置watch,以接收网关的commit或abort结果。
  3. 库存服务也做同样的操作
  4. 网关收到子节点数据变更的通知,统计结果,确定是commit或abort,把结果写入到父节点中
  5. 子节点收到父节点数据变更的通知,根据父节点的内容提交或回滚数据。

注意:之所以由服务创建子节点而不是直接由网关创建创建子节点,是因为服务创建临时子节点,当服务挂掉的时候,子节点会被删除,这样网关就能收到通知,做出相应的处理。

zookeeper如果要实现三段提交和两段提交差不多,稍作调整即可。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值