理解分布式事务的两阶段提交2pc

前言:

    这两天在尝试着看关于分布式系统中的常用协议和框架的文档,比较感兴趣的是分布式事务, 我常常会想一个场景,小明给小红汇钱的时候,如果中间悲催的出现xx问题怎么办?


我们知道可以用事务解决 ! 往往较大型网站及应用都是分布式部署的,数据库层面会拆解分库都不同的mysql服务器上。  这个时候就要上分布式事务了。 趁着热乎劲说下两阶段提交2pc的原理及实现。 

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。

http://xiaorui.cc/2016/02/25/%E7%90%86%E8%A7%A3%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E7%9A%84%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A42pc/

那么什么是分布式事务—两阶段提交协议 ? 

两阶段提交协议(Two-phase Commit,2PC)经常被用来实现分布式事务。一般分为协调器和若干事务执行者两种角色,这里的事务执行者就是具体的数据库,抽象点可以说是可以控制给数据库的程序。 协调器可以和事务执行器在一台机器上。

在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的成功或失败。当一个事务跨越多个节点时,为了保持事务的ACID特性,需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)。


我们设想从支付宝里转10000元到余额宝的场景… … 

1) 首先我们的应用程序发起一个请求到协调器, 然后由控制器来保证分布式事务。

2) 准备凭证阶段 

1. 协调器先将<prepare>消息写到本地日志

2. 向所有的参与者发起<prepare>消息。以支付宝转账到余额宝为例,协调器给A的prepare消息是通知支付宝数据库相应账目扣款10000,协调器给B的prepare消息是通知余额宝数据库相应账目增加10000。

注:
为什么在执行任务前需要先写本地日志,主要是为了故障后恢复用,本地日志起到现实生活中凭证 的效果,如果没有本地日志(凭证),出问题容易死无对证;

参与者收到<prepare>消息后,执行具体本机事务,但不会进行commit,如果成功返回<yes>,不成功返回<no>。同理,返回前都应把要返回的消息写到日志里,当作凭证。

支付宝:

#author: rfyiamcool@163.com

BEGIN WORK
    select money from zhifubao where user='xiaorui' for update;
    update zhifubao set money=money-10000 where user='xiaorui';
    ...
    Operation N
 
 向协调者发送YES或者NO !

 等待协调者的指令过来 !
 

余额宝:

#blog: xiaorui.cc
BEGIN WORK
    select money from yuebao where user='xiaorui' for update;
    update yuebao set money=money+10000 where user='xiaorui';
    ...
    Operation N

根据状态向协调者发送YES或者NO !

然后等待协调者的指令过来 ... ....
 

4) 协调器收集所有执行器返回的消息,如果所有执行器都返回yes,那么给所有执行器发生送commit消息,执行器收到commit后执行本地事务的commit操作;如果有任一个执行器返回no,那么给所有执行器发送abort消息,执行器收到abort消息后执行事务abort操作。

#blog: xiaorui.cc

if 协调者指令 == "to_commit":
    commit work  #提交事务
else:
    ROLLBACK #回滚

注:

     协调器或参与者把发送或接收到的消息先写到日志里,主要是为了故障后恢复用。举个例子,比如某个参与者从故障中恢复后,先检查本机的日志,如果已收到<commit >,则提交,如果<abort >则回滚。如果是<yes>,则再向控制器询问一下,确定下一步。如果什么都没有,则很可能在<prepare>阶段Si就崩溃了,因此需要回滚。

二阶段提交协议虽然相对简单,但他的性能不咋地,根本不适合高并发的系统。为什么?

1)两阶段提交涉及多次节点间的网络通信,通信时间太长!
2)事务时间相对于变长了,锁定的资源的时间也变长了,造成资源等待时间也增加好多!
正是由于分布式事务存在很严重的性能问题,大部分高并发服务都在避免使用,往往通过其他途径来解决数据一致性问题。

现在很多处理流程(Workflow)都会借鉴2PC这个算法,所以还是有学习的场景的。  下面我们再总结下二阶段提交的流程。

上图是正常的场景 ! 只要参与值返回yes,协调者就会发送commit提交指令。 

下图是出错的场景,不管是网络异常中断,对端服务超时或异常,这对于分布式事务来说都是一次失败的任务,会触发abort中断,回滚事务。



参考链接:

http://blog.jobbole.com/89140/


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

2 Responses

  1. 广告not found 2016年11月2日 / 下午12:26

    广告在哪里。。。。。。。

    • 峰云就她了 2016年11月2日 / 下午5:58

      哎, 能不能别这么气人…. 你是不是开AdBlock过滤广告了 …

发表评论

邮箱地址不会被公开。 必填项已用*标注