数据库的事务ACID:原子性,隔离性,一致性,持久性。
事务的隔离级别:脏读,不可重复读,幻读
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点上。
例子:电商系统的订单系统和库存系统
图中包含了库存和订单两个独立的微服务,每个微服务维护了自己的数据库。在交易系统的业务逻辑中,一个商品在下单之前需要先调用库存服务,进行扣除库存,在调用订单服务,创建订单记录。
正常情况下,两个数据库各自更新成功,两边的数据维持着一致性。
如果在非正常情况下,可能库存的扣减完成,随后的订单记录却因为某些原因插入失败。或者订单创建成功,但是库存扣减的数据量失败,这时两边的数据量失去了应有的一致性。
这时候就绪哟为了保证事务的一致性,单数据源的用单机事务来保证,多数据源就需要依赖分布式事务来处理。
XA 协议由 OracleTuxedo 首先提出的,并交给 X/Open 组织,作为资源管理器(数据库) 与事务管理器的接口标准。目前,Oracle、Informix、DB2 和 Sybase 等各大数据库厂家都提 供对 XA 的支持。XA 协议采用两阶段提交方式来管理分布式事务。XA 接口提供资源管理 器与事务管理器之间进行通信的标准接口。
XA 就是 X/OpenDTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交 易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。XA 接口函数由数据库厂 商提供。
X/Open 组织(即现在的 OpenGroup)定义了分布式事务处理模型。X/Open DTP 模型 (1994)包括应用程序(AP)、事务管理器(TM)、资源管理器(RM)、通信资源管理 器(CRM)四部分。一般常见的事务管理器(TM)是交易中间件,常见的资源管理器(RM) 是数据库,常见的通信资源管理器(CRM)是消息中间件。
如果在程序中开启了事务,那么在应用程序发出提交/回滚请求后,数据库执行操作, 而后将成功/失败返回给应用程序,程序继续执行。
一阶段提交协议相对简单。优点也很直观,它不用再与其他的对象交互,节省了判断 步骤和时间,所以在性能上是在阶段提交协议中最好的。但缺点也很明显:数据库确认执行 事务的时间较长,出问题的可能性就随之增大。如果有多个数据源,一阶段提交协议无法协 调他们之间的关系。
注意:一阶段提交事务,不能解决分布式事务,只能用于单体架构项目。
二阶段协议通过将两层变为三层,增加了中间的管理者角色,从而协调多个数 据源之间的关系,二阶段提交协议分为两个阶段。
应用程序调用了事务管理器的提交方法,此后第一阶段分为两个步骤:
事务管理器通知参与该事务的各个资源管理器,通知他们开始准备事务。
资源管理器接收到消息后开始准备阶段,写好事务日志并执行事务,但不提交,然后将 是否就绪的消息返回给事务管理器(此时已经将事务的大部分事情做完,以后的内容耗时极 小)。
第二阶段也分为两个步骤:
事务管理器在接受各个消息后,开始分析,如果有任意其一失败,则发送回滚命令,否 则发送提交命令。
各个资源管理器接收到命令后,执行(耗时很少),并将提交消息返回给事务管理器。 事务管理器接受消息后,事务结束,应用程序继续执行。
为什么要分两步执行?一是因为分两步,就有了事务管理器统一管理的机会;二尽可能晚地提交事务,让事务在提交前尽可能地完成所有能完成的工作,这样,最后的提交阶 段将是耗时极短,耗时极短意味着操作失败的可能性也就降低。
同时,二阶段提交协议为了保证事务的一致性,不管是事务管理器还是各个资源管 理器,每执行一步操作,都会记录日志,为出现故障后的恢复准备依据。
缺点:
1 二阶段提交协议的存在的弊端是阻塞,因为事务管理器要收集各个资源管理器的响应 消息,如果其中一个或多个一直不返回消息,则事务管理器一直等待,应用程序也被阻塞, 甚至可能永久阻塞。
2 两阶段提交理论的一个广泛工业应用是 XA 协议。目前几乎所有收费的商业数据库都 支持 XA 协议。XA 协议已在业界成熟运行数十年,但目前它在互联网海量流量的应用场景 中,吞吐量这个瓶颈变得十分致命,因此很少被用到
TCC 是由支付宝架构师提供的一种柔性解决分布式事务解决方案,主要包括三个步骤 (三个接口)
Try:预留业务资源/数据效验
Confirm:确认执行业务操作
Cancel:取消执行业务操作
与XA的区别:事务的管理者是以一个独立的服务出现,而不是中间件
TCC 方案在电商、金融领域落地较多。TCC 方案其实是两阶段提交的一种改进。其 将整个业务逻辑的每个分支显式的分成了 Try、Confirm、Cancel 三个操作。Try 部分完成 业务的准备工作,confirm 部分完成业务的提交,cancel 部分完成事务的回滚。基本原理如 下图所示。
**优点:**让应用自己定义数据库操作的粒度,使得降低锁冲突、提高吞吐量称为可能。
**缺点:**对应用的侵入性强。业务逻辑的每个分支都需要实现 try、confirm、cancel 三个操作,应用侵入性较强,改造成本高。 实现难度较大。需要按照网络状态、系统故障等不同的失败原因实现不同的 回滚策略。为了满足一致性的要求,confirm 和 cancel 接口必须实现幂等(多次操作时只执行一次操作)。
分布式事务中间件其本身并不创建事务,而是基于对本地事务的协调从而达到事务一致性 的效果。典型代表有:阿里的 GTS(https://www.aliyun.com/aliware/txc)、开源应用 LCN。
用来解决分布式事务。
特点:不是数据库中间件产品,采用柔性事务机制,需要事务协调器
tx-lcn 官方地址:https://www.txlcn.org/
tx-lcnGithub 地址:https://github.com/codingapi/tx-lcn
tx-lcn 服务下载地址:https://pan.baidu.com/s/1cLKAeE#list/path=%2F
tx-lcn 服务源码地址:https://github.com/codingapi/tx-lcn/tree/master/tx-manager
事务组:当前所涉及的所有事务的集合
创建事务组是指在事务发起方开始执行业务代码之前先调用 TxManager 创建事务组 对象,然后拿到事务标示 GroupId 的过程。
添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息添加通知给 TxManager 的操作。
是指在发起方执行完业务代码以后,将发起方执行结果状态通知给 TxManager 的动 作。当执行完关闭事务组的方法以后,TxManager 将根据事务组信息来通知相应的参与模 块提交或回滚事务。
提交的时候是提交给谁呢?
是提交给了我们的 TxClient 模块。然后 TxCliient 模块下有一个连接池,就是框架自定 义的一个连接池(如图 DB 连接池);这个连接池其实就是在没有通知事务之前一直占有着 这次事务的连接资源,就是没有释放。但是他在切面里面执行了 close 方法。在执行 close 的时候。如果需要(TxManager)分布式事务框架的连接。他被叫做“假关闭”,也就是没有 关闭,只是在执行了一次关闭方法。实际的资源是没有释放的。这个资源是掌握在 LCN 的 连接池里的。
当 TxManager 通知提交或事务回滚的时候呢?
TxManager 会通知我们的 TxClient 端。然后 TxClient 会去执行相应的提交或回滚。提交 或回滚之后再去关闭连接。这就是 LCN 的事务协调机制。说白了就是代理 DataSource 的机 制;相当于是拦截了一下连接池,控制了连接池的事务提交。
LCN 的补偿事务原理是模拟上次失败事务的请求,然后传递给 TxClient 模块然后再次 执行该次请求事务。
简单的说:lcn 事务补偿是指在服务挂机和网络抖动情况下 txManager 无法通知事务单 元时。(通知不到也就两种原因服务挂了和网络出问题)在这种情况下 TxManager 会做一 个标示;然后返回给发起方。告诉他本次事务有存在没有通知到的情况。
那么如果是接收到这个信息之后呢,发起方就会做一个标示,标示本次事务是需要补偿 事务的。这就是事务补偿机制。
事务补偿是指在执行某个业务方法时,本应该执行成功的操作却因为服务器挂机或者网 络抖动等问题导致事务没有正常提交,此种场景就需要通过补偿来完成事务,从而达到事务 的一致性(2种情况,实时一致性:当前操作必须保证一致性;最终一致性:未提交成功,但是一段时间之后,在提交只要保证一致即可)。
当执行关闭事务组步骤时,若发起方接受到失败的状态后将会把该次事务识别为待补偿 事务,然后发起方将该次事务数据异步通知给 TxManager。TxManager 接受到补偿事务以后 先通知补偿回调地址,然后再根据是否开启自动补偿事务状态来补偿或保存该次切面事务数 据
创建三个服务分别为:springcloud-portal、springcloud-order、springcloud-inventory。在 springcloud-portal 服务中处理创建订单的请求,然后分别请求 springcloud-order 以及 springcloud-inventory服务。在springcloud-order中插入一条订单数据,在springcloud-inventory 中对商品的数量做更新。
数据库:Mysql
开发平台:SpringCloud+SpringBoot+MyBatis
创建两个数据库分别为: sxt_orders, sxt_inventory。 springcloud-order 操作 sxt_orders 库, springclooud-inventory 操作 sxt_inventory 库
pom文件:
application.properties配置文件
pom文件:
application.properties配置文件
pom文件:
application.properties配置文件