`
m635674608
  • 浏览: 4905276 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

分布式事务 - 两阶段提交与三阶段提交

 
阅读更多

 在分布式系统中,著有CAP理论,该理论由加州大学伯克利分校的Eric Brewer教授提出,该理论阐述了在一个分布式系统中不可能同时满足一致性(Consistency)、可用性(Availability),以及分区 容错性(Partition tolerance)。

  • 一致性
    在分布式系统中数据往往存在多个副本,一致性描述的是这些副本中的数据在内容和组织上的一致。
  • 可用性
    可用性描述了系统对用户的服务能力,所谓可用是指在用户容忍的时间范围内返回用户期望的结果。
  • 分区容错性
    分布式系统通常由多个节点构成,这些节点通常分布在不同的网络中,然而网络始终是不可靠的,所以存在分布式集群中的节点因为网络通信故障导致被孤立成一个个小集群的可能性,分区容错性要求在出现这种情况下系统仍然能够对外提供一致性的可用服务。

  对于一个分布式系统,我们始终要假设网络是不可靠的,所以分区容错性是对一个分布式系统最基本的要求,所以我们更多的是尝试在可用性和一致性之 间寻找一个平衡点。让分布式集群始终对外提供可用的一致性服务一直是富有挑战和趣味的一项任务。暂且抛开可用性,拿一致性来说,对于关系型数据库我们通常 利用事务来保证数据的一致性,当我们的数据量越来越大,大到单库已经无法承担时,我们不得不采取分库分表的策略对数据库实现拆分,构建分布式数据库集群, 这样可以将一个数据库的压力分摊到多个数据库,极大的提升了数据库的存储和响应能力,但是也为我们使用数据库带来了许多的限制,比如主键的全局唯一、联表 查询、数据聚合等等,另外一个相当棘手的问题就是数据库的事务由原先的单库事务变成了现在的分布式事务。
  分布式事务的实现并不是很难,比如下 文要展开的两阶段提交(2PC:Two-Phrase Commit)和三阶段提交(3PC:Three-Phrase Commit)都给我们提供了思路,但是如果要保证数据的强一致性,并要求对外提供可用的服务,那么就变成了一个几乎不可能的任务(至少目前是),因此很 多分布式系统对于数据强一致性都敬而远之,本人在之前项目的架构设计中也花费不少时间在系统的一致性和可用性之间寻找平衡。

 

两阶段提交协议(2PC:Two-Phrase Commit)

  两阶段提交协议的目标在于在分布式系统中保证数据的一致性,许多分布式系统采用该协议提供对分布式事务的支持(提供但不一定有人用,呵呵~)。 顾名思义,该协议将一个分布式的事务过程拆分成两个阶段:投票阶段和事务提交阶段。为了让整个数据库集群能够正常的运行,该协议指定了一个“协调者”单 点,用于协调整个数据库集群的运行,为了简化描述,我们将数据库里面的各个节点称为“参与者”,三阶段提交协议中同样包含“协调者”和“参与者”这两个定 义。

 

第一阶段:投票阶段

该阶段的主要目的在于打探数据库集群中的各个参与者是否能够正常的执行事务,具体步骤如下:

1. 协调者向所有的参与者发送事务执行请求,并等待参与者反馈事务执行结果。
2. 事务参与者收到请求之后,执行事务,但不提交,并记录事务日志。
3. 参与者将自己事务执行情况反馈给协调者,同时阻塞等待协调者的后续指令。

 

第二阶段:事务提交阶段

在第一阶段协调者的询盘之后,各个参与者会回复自己事务的执行情况,这时候存在三种可能:

1. 所有的参与者回复能够正常执行事务
2. 一个或多个参与者回复事务执行失败
3. 协调者等待超时。

对于第一种情况,协调者将向所有的参与者发出提交事务的通知,具体步骤如下:

1. 协调者向各个参与者发送commit通知,请求提交事务。
2. 参与者收到事务提交通知之后,执行commit操作,然后释放占有的资源。
3. 参与者向协调者返回事务commit结果信息。

事务提交时序图

对于第二、三种情况,协调者均认为参与者无法正常成功执行事务,为了整个集群数据的一致性,所以要向各个参与者发送事务回滚通知,具体步骤如下:

1. 协调者向各个参与者发送事务rollback通知,请求回滚事务。
2. 参与者收到事务回滚通知之后,执行rollback操作,然后释放占有的资源。
3. 参与者向协调者返回事务rollback结果信息。

事务回滚时序图

  两阶段提交协议解决的是分布式数据库数据强一致性问题,其原理简单,易于实现,但是缺点也是显而易见的,主要缺点如下:

  • 单点问题
    协调者在整个两阶段提交过程中扮演着举足轻重的作用,一旦协调者所在服务器宕机,那么就会影响整个数据库集群的正常运行,比如在第二阶段中,如果协调者因为故障不能正常发送事务提交或回滚通知,那么参与者们将一直处于阻塞状态,整个数据库集群将无法提供服务。

  • 同步阻塞
    两阶段提交执行过程中,所有的参与者都需要听从协调者的统一调度,期间处于阻塞状态而不能从事其他操作,这样效率及其低下。

  • 数据不一致性
    两阶段提交协议虽然为分布式数据强一致性所设计,但仍然存在数据不一致性的可能,比如在第二阶段中,假设协调者发出了 事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了commit操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这 时候就产生了数据的不一致性。

 

三阶段提交协议(2PC:Three-Phrase Commit)

  针对两阶段提交存在的问题,三阶段提交协议通过引入一个“预询盘”阶段,以及超时策略来减少整个集群的阻塞时间,提升系统性能。三阶段提交的三个阶段分别为:can_commit,pre_commit,do_commit。

 

第一阶段:can_commit

  该阶段协调者会去询问各个参与者是否能够正常执行事务,参与者根据自身情况回复一个预估值,相对于真正的执行事务,这个过程是轻量的,具体步骤如下:

1. 协调者向各个参与者发送事务询问通知,询问是否可以执行事务操作,并等待回复
2. 各个参与者依据自身状况回复一个预估值,如果预估自己能够正常执行事务就返回确定信息,并进入预备状态,否则返回否定信息

 

第二阶段:pre_commit

本阶段协调者会根据第一阶段的询盘结果采取相应操作,询盘结果主要有三种:

1. 所有的参与者都返回确定信息
2. 一个或多个参与者返回否定信息
3. 协调者等待超时

针对第一种情况,协调者会向所有参与者发送事务执行请求,具体步骤如下:

1. 协调者向所有的事务参与者发送事务执行通知
2. 参与者收到通知后,执行事务,但不提交
3. 参与者将事务执行情况返回给客户端

在上面的步骤中,如果参与者等待超时,则会中断事务。 针对第二、三种情况,协调者认为事务无法正常执行,于是向各个参与者发出abort通知,请求退出预备状态,具体步骤如下:

1. 协调者向所有事务参与者发送abort通知
2. 参与者收到通知后,中断事务

事务中断时序图

 

第三阶段:do_commit

  如果第二阶段事务未中断,那么本阶段协调者将会依据事务执行返回的结果来决定提交或回滚事务,分为三种情况:

1. 所有的参与者都能正常执行事务
2. 一个或多个参与者执行事务失败
3. 协调者等待超时

针对第一种情况,协调者向各个参与者发起事务提交请求,具体步骤如下:

1. 协调者向所有参与者发送事务commit通知
2. 所有参与者在收到通知之后执行commit操作,并释放占有的资源
3. 参与者向协调者反馈事务提交结果

事务提交时序图
针对第二、三种情况,协调者认为事务无法正常执行,于是向各个参与者发送事务回滚请求,具体步骤如下:

1. 协调者向所有参与者发送事务rollback通知
2. 所有参与者在收到通知之后执行rollback操作,并释放占有的资源
3. 参与者向协调者反馈事务提交结果

事务回滚时序图
  在本阶段如果因为协调者或网络问题,导致参与者迟迟不能收到来自协调者的commit或rollback请求,那么参与者将不会如两阶段提交中那样陷入阻塞,而是等待超时后继续commit。相对于两阶段提交虽然降低了同步阻塞,但仍然无法避免数据的不一致性。

  在分布式数据库中,如果期望达到数据的强一致性,那么服务基本没有可用性可言,这也是为什么许多分布式数据库提供了跨库事务,但也只是个摆设的原因,在实际应用中我们更多追求的是数据的弱一致性或最终一致性,为了强一致性而丢弃可用性是不可取的。

 

http://my.oschina.net/wangzhenchao/blog/736909

分享到:
评论
1 楼 小黄牛 2016-11-16  
分布式事务数据一致性推荐一个参考文章:
http://www.roncoo.com/article/detail/124243

相关推荐

    分布式事务思想和分布式系统入门.txt

    交易中间件与数据库通过 XA 接口规范,使用两阶段提交来完成一个全局事务, XA 规范的基础是两阶段提交协议。 第一阶段是表决阶段,所有参与者都将本事务能否成功的信息反馈发给协调者;第二阶段是执行阶段,协调者...

    分布式事务入门GitChat问题实录解答

    单数据库的事物隔离级别, 三阶段协议币两阶段提交协议多了一个阶段,那么多出来的那一个阶段操作带来什么好处

    分布式事务之rabbitmq肉身实战

    分布式系统最终一致性有N种方案,比如2PC(2阶段事务),以及三段提交等等,但开销较大,实现起来复杂,比如2阶段事务为例,需要引入一个协调者(Coordinator)来统一掌控所有参与者(Participant)的操作结果 ...

    2021年数据库研究报告

    经过多年的发展,各数据库厂商提出了多种分布式事务解决方案,例如两阶段提交(2PC)/三阶段提交(3PC)、TCC方案、可靠消息最终一致性(本地消息表方案-eBay、RocketMQ 事务消息方案-阿里/Apache)、最大努力通知...

    12、高并发、高可用、分布式(9题)1

    1. 高并发原则 2. 高可用原则 3. 业务设计原则 4. 总结 5. 分布式与集群的区别: 6. 分布式事务: 1. 二阶段提交: 2. 三阶段提交: 3.

    4、乐信(25问)1

    1.画出项目的架构图 2.所处自己负责的业务模块,其中用到了哪些技术点 3.如何实现最终一致性分布式事务 1. 二阶段提交: 2. 三阶段提交: 3. 柔性事务

    Fourinone分布式并行计算四合一框架

     4、两阶段提交和事务补偿处理  5、自带一个集群文件浏览器,可以查看集群所有硬盘上的文件(不同于hadoop的namenode,没有单点问题和容量限制)  总的来说, 将集群看做一个操作系统,像操作本地文件一样操作远程...

    事务讨论笔记

    XA 是一个两阶段提交协议,该协议分为以下两个阶段: 第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交. 第二阶段:事务协调器要求每个数据库提交数据。 BASE理论 ...

    Redis学习笔记—Redis事务

    前言 Redis事务可以一次执行多个命令(按顺序地串行执行,执行中不会被其他命令插入,不许加塞) 1.简介 Redis事务可以一次执行多个命令(允许在一次单独的步骤中执行一组...2.事务的处理的阶段与错误处理机制 [1] 三个阶

    xaplus-engine:基于XA和XA +协议的事务处理引擎

    这是两阶段协议,其中包含准备事务和决定提交/回滚的步骤。 接下来,引擎使用XA +接口(请参阅2)与全局事务参与者之间进行通信。 上级引擎或全局事务的发起者还可以使事务记录事务的所有决策,并在需要时进行...

    三层C/S结构编程指南

    本书详细介绍了三层客户机服务器结构的系统结构,从计算机体系结构的变迁,三层结构的优点,一些常见概念,如数据的一致性、两阶段提交、分布式事务处理、事务处理器以及XA规范的系统说明,到CICS是如何构造以...

    优惠卷系统Go语言实现

    涉及发劵 领劵 用劵 触达系统 劵的分布式事务 ...总共有三个阶段:确认订单 提交订单 支付订单 技术难点解决:分布式事务TCC 用RabbitMQ 实现大规模发劵 解决了高并发的问题 代码实现了商家侧和用户侧的逻辑

    数据库系统实现

    书中对数据库系统实现原理进行了深入阐述,并具体讨论了数据库管理系统的三个主要成分—存储管理器、查询处理器和事务管理器的实现技术。书中还对信息集成的最新技术,例如数据仓库、OLAP、数据挖掘、Mediator、数据...

    数据库系统-招标参数---模板.doc

    具有多种复制功能模块 " " " "支持ODBC 3.0、X/Open XA、CLI、JDBC等标准 " " " "支持分布式事务及两阶段提交功能 " " " "支持动态将锁粒度调整到合适的级别,支持动态行" " " "级锁定 " " " "支持高可用性组,可以...

    java面试常见基础(深层次,高级研发)

    19.2. 2 两阶段提交协议 47 19.2.1. 2.1 预提交阶段 48 19.2.2. 2.2 提交阶段 48 19.3. 3 分布式事务应用框架 48 19.3.1. 3.1 角色 48 19.3.2. 3.2 交互时序 49 19.3.3. 3.3 关键点 50 19.3.4. 参考 50 20. Jvm底层...

    Atomikos3.9官方包文档以及实例

    XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。 以下的函数使事务管理器可以对资源管理器进行的操作: 1)...

    淘淘商城taotao.mail

    三阶段提交协议,是二阶段提交协议的改进阶段,插入了一个preCommit阶段,使得原先的二阶段提交 执行步骤: 1.协调者向所有参与者发出包含的事务内容的canCommit请求,询问是否可以提交事务,并等待所有参与者回复 2....

Global site tag (gtag.js) - Google Analytics