文章目录

  • 数据库事务
    • 数据库事务的特性
    • 事物隔离级别
    • 脏读、不可重复读、幻读
  • 分布式事务
    • 分布式事务产生的原因
      • Service 产生多个节点 (服务)
      • Resource 产生多个节点 (存储)
    • 分布式事物基础
      • CAP定理
      • BASE理论
    • 一、2PC (两阶段提交)
      • 1、准备阶段
      • 2、提交阶段
      • 3、优点
      • 4、缺点
    • 二、3PC (三阶段提交)
      • 1、CanCommit阶段
      • 2、PreCommit阶段
      • 3、doCommit阶段
      • 4、优点
      • 5、缺点
    • 三、TCC(`Try - Confirm - Cancel`)
    • 四、本地消息表(异步确保)
    • 五、MQ事务消息
    • 六、提供回滚接口(同步执行)
  • 总结

数据库事务

数据库事务的特性

原子性(Atomicity )、一致性( Consistency )、隔离性( Isolation)和持久性(Durabilily),简称就是ACID。

  • Atomicity(原子性):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

  • Consistency(一致性):事务开始前和结束后,数据库的完整性约束没有被破坏 。

  • Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

    事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

  • Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

事物隔离级别

MySQL 的事务隔离是在 MySQL.ini 配置文件里添加的,在文件的最后添加:

transaction-isolation = REPEATABLE-READ
  • READ-UNCOMMITTED:读-未提交,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)。
  • READ-COMMITTED:读-已提交,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读)。
  • REPEATABLE-READ:可重复读,默认级别,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读)。
  • SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。

脏读、不可重复读、幻读

  • 脏读 : 事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

  • 不可重复读 : 事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

  • 幻读 : 系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

  • 小结 : 不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

分布式事务

分布式事务产生的原因

从上面本地事务来看,我们可以分为两块:

Service 产生多个节点 (服务)

随着互联网快速发展,微服务,SOA等服务架构模式正在被大规模的使用,举个简单的例子,一个公司之内,用户的资产可能分为好多个部分,比如余额,积分,优惠券等等。在公司内部有可能积分功能由一个微服务团队维护,优惠券又是另外的团队维护。这样的话就无法保证积分扣减了之后,优惠券能否扣减成功。

Resource 产生多个节点 (存储)

同样的,互联网发展得太快了,我们的Mysql一般来说装千万级的数据就得进行分库分表,对于一个支付宝的转账业务来说,你给的朋友转钱,有可能你的数据库是在北京,而你的朋友的钱是存在上海,所以我们依然无法保证他们能同时成功。

分布式事物基础

分布式事务是随着互联网高速发展应运而生的,数据库的 ACID 四大特性,已经无法满足我们分布式事务,这个时候又提出一些新的理论。

CAP定理

CAP定理指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼

  • 一致性(Consistency) :更新操作成功后,所有节点在同一时间的数据完全一致。

  • 可用性(Availability) : 用户访问数据时,系统是否能在正常响应时间返回结果。

  • 分区容错性(Partition tolerance) : 分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。

BASE理论

BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually Consistent (最终一致性)三个短语的缩写,是对 CAP中AP的一个扩展。

  • Basically Available(基本可用):分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。

  • Soft state(软状态):允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是 CAP 中的不一致。

  • Eventually Consistent (最终一致性):最终一致是指经过一段时间后,所有节点数据都将会达到一致。

BASE 解决了 CAP 中理论没有网络延迟,在 BASE 中用软状态和最终一致性,保证了延迟后的一致性。

BASE 和 ACID 是相反的,它完全不同于 ACID 的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。

一、2PC (两阶段提交)

两阶段提交(Two-phase Commit,2PC),通过引入协调者来协调参与者的行为,并最终决定这些参与者是否要真正执行事务。

1、准备阶段

协调者询问参与者事务是否执行成功,参与者发回事务执行结果。

2、提交阶段

如果事务在每个参与者上都执行成功,事务协调者发送通知让参与者提交事务;否则,协调者发送通知让参与者回滚事务。

需要注意的是,在准备阶段,参与者执行了事务,但是还未提交。只有在提交阶段接收到协调者发来的通知后,才进行提交或者回滚。

3、优点

  • 原理简单

  • 实现方便

4、缺点

  • 同步阻塞: 所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作。
  • 单点问题: 协调者在 2PC 中起到非常大的作用,发生故障将会造成很大影响。特别是在阶段二发生故障,所有参与者会一直等待状态,无法完成其它操作。
  • 网络分区导致数据不一致: 在阶段二,如果协调者只发送了部分 Commit 消息,此时网络发生异常,那么只有部分参与者接收到 Commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
  • 太过保守: 任意一个节点失败就会导致整个事务失败,没有完善的容错机制。

二、3PC (三阶段提交)

三阶段提交(Three-phase commit),也叫三阶段提交协议(Three-phase commit protocol),是二阶段提交(2PC)的改进版本。2PC 和 3PC 都是数据库层面的。

与两阶段提交不同的是,三阶段提交有两个改动点。

  1. 在协调者和参与者中都引入超时机制。
  2. 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。

也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。

1、CanCommit阶段

协调者向参与者发送commit请求,参与者如果可以提交就返回Yes,否则返回No。

2、PreCommit阶段

协调者根据参与者的反应情况来决定是否可以记性事务的PreCommit操作。根据响应情况,有以下两种可能。

  • 假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务的预执行。
  • 假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。

3、doCommit阶段

该阶段进行真正的事务提交,也可以分为以下两种情况。

  • 执行提交
  • 中断事务

需要注意的是,一旦进入阶段三,可能会存在以下两种故障。

  • 协调者出现问题。
  • 协调者和参与者之间的网络出现故障。

无论出现哪种情况,最终都会导致参与者无法及时接收到来自协调者的doCommit或是abort请求,针对这样的异常情况,参与者都会在等待超时之后,继续进行事务提交。

4、优点

相较于二阶段提交协议,三阶段提交协议最大的优点就是降低了参与者的阻塞范围,并且能够在出现单点故障后继续达成一致

5、缺点

三阶段提交协议在去除阻塞的同时也引入了新的问题,那就是在参与者接收到preCommit消息后,如果网络出现分区,此时协调者所在的节点和参与者无法进行正常的网络通信,在这种情况下,该参与者依然会进行事务的提交,这必然出现数据的不一致

三、TCC(Try - Confirm - Cancel

2PC 和 3PC 都是数据库层面的,而 TCC 是业务层面的分布式事务,就像我前面说的分布式事务不仅仅包括数据库的操作,还包括发送短信等,这时候 TCC 就派上用场了!

TCC 指的是Try - Confirm - Cancel。

  • Try 指的是预留,即资源的预留和锁定,注意是预留。
  • Confirm 指的是确认操作,这一步其实就是真正的执行了。
  • Cancel 指的是撤销操作,可以理解为把预留阶段的动作撤销了。

其实从思想上看和 2PC 差不多,都是先试探性的执行,如果都可以那就真正的执行,如果不行就回滚。

这种处理方式的前提是面对事务都要有一套确认事务执行的业务,一套取消执行的业务(即补偿业务)。比如说减库存这个业务,确认事务就是减库存,补偿事务就是加库存。

这种处理方式时所有业务都开始执行,互相不等待,完成了就提交,解决了两阶段提交问题中数据大面积锁定的情况,但是如果业务A已经提交了,但是业务B失败了,没关系,会调用所有的补偿事务,这种解决方案不是靠事务回滚的方式,靠的是事务的补偿。

还有一点要注意,撤销和确认操作的执行可能需要重试,因此还需要保证操作的幂等。

可以看到流程还是很简单的,难点在于业务上的定义,对于每一个操作你都需要定义三个动作分别对应Try - Confirm - Cancel。

优点:相对于 2PC、3PC ,TCC 适用的范围更大,不过也因为是在业务上实现的,所以TCC可以跨数据库、跨不同的业务系统来实现事务。

缺点:解决了业务问题,但是使得业务变得复杂了,写一个业务必须写一个确定执行业务方法和一个补偿业务方法,除此之外还要考虑补偿方案的失败问题,当补偿方案也执行失败了呢,这时候就要考虑重试问题、人工介入问题。

综上,在电商行业中适用的还是TCC,虽然业务变得复杂了,但是行之有效;如果是转账业务,适合异步确保,转账业务只需要消息可靠就可以,执行时间晚一点也无妨,所以异步确保的关键点是消息的可靠

四、本地消息表(异步确保)


本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。

具体怎么做呢?

  1. 消息生产方(也就是发起方),需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。
  2. 消息消费方(也就是发起方的依赖方),需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会进入定时任务重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。
  3. 如果调用失败,后台定时任务定时扫描本地消息表,把还没处理完成的消息进行重试或者失败的消息再发送一遍。重试就得保证对应服务的方法是幂等的,而且一般重试会有最大次数,超过最大次数可以记录下报警让人工处理。

实例:

可以看到本地消息表其实实现的是最终一致性,容忍了数据暂时不一致的情况。

  • 优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。
  • 缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。

五、MQ事务消息

RocketMQ 就很好的支持了消息事务,让我们来看一下如何通过消息实现事务。

第一步先给 Broker 发送事务消息即半消息,半消息不是说一半消息,而是这个消息对消费者来说不可见,然后发送成功后发送方再执行本地事务。

再根据本地事务的结果向 Broker 发送 Commit 或者 RollBack 命令。

并且 RocketMQ 的发送方会提供一个反查事务状态接口,如果一段时间内半消息没有收到任何操作请求,那么 Broker 会通过反查接口得知发送方事务是否执行成功,然后执行 Commit 或者 RollBack 命令。

如果是 Commit 那么订阅方就能收到这条消息,然后再做对应的操作,做完了之后再消费这条消息即可。

如果是 RollBack 那么订阅方收不到这条消息,等于事务就没执行过。

可以看到通过 RocketMQ 还是比较容易实现的,RocketMQ 提供了事务消息的功能,我们只需要定义好事务反查接口即可。

  • 优点: 实现了最终一致性,不需要依赖本地数据库事务。

  • 缺点: 实现难度大,主流MQ不支持,RocketMQ事务消息部分代码也未开源。

六、提供回滚接口(同步执行)

  1. 订单系统生成订单号,扔给一个差错恢复系统(存储在自己的db)
  2. 订单系统拿订单号调用库存系统,如果失败,则回滚库存(不管回滚成功或者失败,都通知前台失败)
  3. 订单系统拿订单号调用优惠券系统减少优惠券,如果失败,则回滚库存、回滚优惠券(不管回滚成功或者失败,都通知前台失败)
  4. 开启本地事物,创建订单记录

差错恢复系统每隔30秒捞取db中订单号,查询订单系统。

  1. 如果订单记录ok,说明数据全部一致
  2. 如果没有订单记录,则根据订单号查询库存系统,如果库存已经回滚,则ok,否则调用库存回滚接口,重试直到成功
  3. 如果没有订单记录,则根据订单号查询优惠券系统,如果优惠券已经回滚,则ok,否则调用优惠券回滚接口,重试直到成功

总结:这种方式缺点比较多,通常在复杂场景下是不推荐使用的,除非是非常简单的场景,非常容易提供回滚,而且依赖的服务也非常少的情况。

这种实现方式会造成代码量庞大,耦合性高。而且非常有局限性,因为有很多的业务是无法很简单的实现回滚的,如果串行的服务很多,回滚的成本实在太高。

总结

可以看出 2PC 和 3PC 是一种强一致性事务,不过还是有数据不一致,阻塞等风险,而且只能用在数据库层面。

而 TCC 是一种补偿性事务思想,适用的范围更广,在业务层面实现,因此对业务的侵入性较大,每一个操作都需要实现对应的三个方法。

本地消息、事务消息其实都是最终一致性事务,因此适用于一些对时间不敏感的业务。

数据库事物和分布式事物相关推荐

  1. 分布式事物(2PC,3PC,CAP,柔性与刚性事物,LCN)

    转载自  https://blog.csdn.net/lizhen1114/article/details/80110317 分布式事物解决方案 分布式事物产生原因:主要产生与在微服务系统中,数据库的 ...

  2. 使用LCN框架解决分布式事物

    使用LCN框架解决分布式事物 更多干货 分布式实战(干货) spring cloud 实战(干货) mybatis 实战(干货) spring boot 实战(干货) React 入门实战(干货) 构 ...

  3. 深入分析事物以及什么是分布式事物?

    什么是事物? 事物是关系型数据库中,由一组sql组成的执行单元,该单元要么整体成功,要么整体失败. 事物的ACID特性 事物ACID特性,原子性,一致性,隔离性,持久性,这4个属性统称为ACID特性. ...

  4. 面试必备的分布式事物方案

    四月初,去面试了本市的一家之前在做办公室无人货架的公司,虽然他们现在在面临着转型,但是对于我这种想从传统企业往互联网行业走的孩子来说,还是比较有吸引力的. 在面试过程中就提到了分布式事物问题.我又一次 ...

  5. 分布式事物一致性设计思路

    本地事务ACID大家应该都知道了,统一提交,失败回滚,严格保证了同一事务内数据的一致性!而分布式事务不能实现这种ACID,它只能实现CAP原则里的某两个,CAP也是分布式事务的一个广泛被应用的原型,C ...

  6. 分布式事物框架--EasyTransaction的入门介绍

    分布式事物框架--EasyTransaction的入门介绍 柔性事务,分布式事务,TCC,SAGA,可靠消息,最大努力交付消息,事务消息,补偿,全局事务,soft transaction, distr ...

  7. 分布式事物框架TCC-Transaction使用教程

    分布式事物框架TCC-Transaction使用教程 本指南适用于tcc-transaction 1.2.x版本.tcc-transaction 1.1.x版的使用指南请参考:使用指南1.1.x 1. ...

  8. 高性能分布式事物中间件Sharding-Sphere介绍

    原作者:Sharding-Sphere 转载来源:http://shardingsphere.io/index.html  , https://github.com/sharding-sphere/s ...

  9. 明了 | 看了这篇文章,多年不能理解的分布式事物,终于看懂了!

    hi !我是小小,我们又见面了,在本篇中,小小将会详细的介绍关于分布式事物的问题,看完了这篇文章,多年来的关于分布式事物的问题全都会了. 基础知识 工欲善其事,必先利其器.所以需要先有一定的基础知识. ...

最新文章

  1. 科研工作者一般怎么找文献?
  2. ZT Android4.2蓝牙基础架构学习
  3. 资讯|WebRTC M92 更新
  4. Linux分区如何表示,Linux中硬盘分区的表示方法
  5. Mybatis一级缓存、整合第三方缓存ehcache、Mybatis二级缓存
  6. 输入框中光标过长原因
  7. python下载官网-python下载官网
  8. python面试问题_Python面试问题
  9. 旋转链表 Java,leetcode 旋转链表 Java
  10. 基础知识(四)C++常用函数.txt
  11. 日本酒店寄送行李至机场的攻略
  12. 多源数据融合算法综述
  13. 亚利桑那州立大学计算机科学排名,2019上海软科世界一流学科排名计算机科学与工程专业排名亚利桑那州立大学排名第76-100...
  14. 使用Flash骨骼工具制作角色动画
  15. 阿里p7程序员哀叹:35岁,被通知合同不再续签
  16. 黑白照片怎么上色?建议使用这几招
  17. 一心多用多线程-线程池ThreadPoolExecutor-看这篇就够了
  18. uCOS2源码分析1-BSP部分-第4季第2部分视频课程-朱有鹏-专题视频课程
  19. iphone 手机尺寸_iPhone是新的黑莓手机
  20. 游戏开发者大会_特别版:游戏开发者大会上的开放游戏

热门文章

  1. JSRUN有什么用?
  2. Java Web之Servlet的三大常用作用域对象及其使用方法
  3. 计算机应用投稿建议,计算机类核心期刊投稿心得【转】 - 计算机软件及计算机应用 - 电子技术及信息科学 - C......
  4. Qt 圆形进度条实现
  5. 蓝牙4.0、经典蓝牙、BT、BLE的关系与区别
  6. 汇编语言 | CALL 和RET指令
  7. PTA 帅到没朋友 (20分)
  8. 小程序 video 控制器外观调整_Razer Kishi 评测:吹破天的手机游戏控制器,真有那么好用吗?...
  9. Java排序之归并排序 1
  10. 2020年数二真题(重点题讲解)