1 分布式事务
1.1 分布式事务是什么?
- 在分布式系统中,事务参与者在不同的分布式节点上或事务操作的数据源不是同一个, 这些情况产生的事务都叫做分布式事务。
- 例如:
项目 A 实现 Tb_item 表新增、项目 B 实现 tb_item_param 新增,现在需要实现商品新增,需要把项目 A 和项目 B 两个项目新增的方法组成一个事务,这个事务就是分布式事务。 - 例如:
项目中向 MySQL 做新增,同时还需要向 Redis 或 MongoDB 执行新增,希望执行 MySQL 或 Redis 或 MongoDB 时如果出现异常进行事务回滚,这种情况也成为分布式事务。
1.2 什么时候使用分布式事务
- 事务的概念最早是在学习数据库(MySQL、Oracle)中接触到的,一个事务(本地事务)就是一系列 SQL 语句的集合,只要在执行过程中一条 SQL 出错就会导致整个事务失败,回滚到原点。而在分布式系统中存在多模块完成一次业务。那么就存在一个业务由多模块操作同一个数据源
- 甚至可能存在一个业务横跨多种数据源节点的可能。这些问题都可以由分布式事务解决方案 TX-LCN 解决
1.3 分布式事务常见解决方案
1.3.1 基于 XA 协议的两阶段提交
分布式事务通常采用 2PC 协议,全称 Two Phase Commitment Protocol。该协议主要为了解决在分布式数据库场景下,所有节点间数据一致性的问题。分布式事务通过 2PC 协议将提交分成两个阶段:
- 1.prepare
2.commit/rollback - 阶段一为准备(prepare)阶段。即所有的参与者准备执行事务并锁住需要的资源。参与者 ready 时,向 transaction manager 报告已准备就绪。
- 阶段二为提交阶段(commit)。当 transaction manager 确认所有参与者都 ready 后,向所有参与者发送 commit 命令
1.3.2 消息事务+最终一致性
- 所谓的消息事务就是基于消息中间件的两阶段提交,本质上是对消息中间件的一种特殊利用,它是将本地事务和发消息放在了一个分布式事务里,保证要么本地操作成功并且对外发消息成功,要么两者都失败
分布式事务,本质上是对多个数据库的事务进行统一控制,按照控制力度可以分为:不控制、部分控制和完全控制。不控制就是不引入分布式事务,部分控制就是各种变种的两阶段提交,包括上面提到的消息事务+最终一致性、TCC 模式,而完全控制就是完全实现两阶段提交。部分控制的好处是并发量和性能很好,缺点是数 据一致性减弱了,完全控制则是牺牲了性能,保障了一致性,具体用哪种方式,最终还是取决于业务场景
2 分布式事务理论依据
- 分布式事务存在两大理论依据:CAP 定理和 BASE 理论
2.1 CAP 定理
- CAP 定理是指在一个分布式系统中 Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),最多同时满足其中两个,三者不可兼得。
2.1.1 一致性(C)
- 在分布式系统中所有节点的状态是一样的。
2.1.2 可用性(A)
- 在集群中一部分节点出现故障后,整个集群是否还能响应客户端请求。
2.1.3 分区容错性(P)
- 以实际效果而言,分区相当于对操作的时限要求。如果系统不能在一定时限内达到数据一致性,就意味着发生了分区的情况,此时就必须在 A 和 C 中做选择。
2.2 BASE 理论
- 是指 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent(最终一致性)三个短语的缩写。
- BASE 理论是对 CAP 中一致性和可用性权衡的结果,是基于 CAP 演化而来的。
- BASE 理论核心思想:即使无法做到强一致性,每个应用都可以根据自身业务特点,采用适当的方式达到最终一致性。
2.2.1 基本可用(BA)
- 是指在分布式系统中出现不可知故障的时候,允许损失部分可用性。此处要注意:损失部分可用性,不代表整个系统不可用
- 例如:
1.可以增加响应时间。由之前 0.5 秒,在出现故障的时候变成 1~2 秒
2.由于一些特殊原因,使网站访问流量激增,为了保证整个系统的稳定性,部分访问者可能被引导到降级页面中
2.2.2 软状态(S)
- 是指系统中数据允许存在中间状态(软状态),并认为这个状态是不影响系统的可用性的。通俗解释:允许分布式节点之间存在同步延迟
- 例如:
在 Eureka 集群中数据同步时就存在软状态
2.2.3 最终一致性
- 允许整个系统中数据在经过一定时间后,最终能达到整个系统的一致性。但是这个时间绝对不可以过长
- 强一致性要求系统接收请求后,整个系统必须达到一致性效果,才会响应结果
- 最终一致性是弱一致性的特例。满足最终一致性的系统在响应给用户结果时整个系统可能是没有达到一致性的,但是最终一定会达到一致性效果的
3 TX-LCN 概述
3.1 简介
- LCN 框架在 2017 年 6 月发布第一个版本
- LCN 早期设计时,1.0 版本和 2.0 版本设计步骤如下:
1.锁定事务单元(Lock)
2.确认事务模块状态(Confirm)
3.通知事务(Notify) - 取各自首字母后名称为 LCN。
- LCN 框架从 5.0 开始兼容了 LCN、TCC、TXC 三种事务模式,为了和 LCN 框架区分,从 5.0 开始把 LCN 框架更名为:TX-LCN 分布式事务框架
3.2 TX-LCN 原理
- TX-LCN 由两大模块组成,TxClient、TxManager
- TxClient 作为模块的依赖框架,提供了 TX-LCN 的标准支持,事务发起方和参与方都属于 TxClient。TxManager 作为分布式事务的控制方,控制整个事务
3.2.1 原理中核心内容
3.2.1.1 创建事务组
- 是指在事务发起方开始执行业务代码之前先调用 TxManager 创建事务组对象,然后拿到事务标识 GroupId 的过程。
3.2.1.2 加入事务组
- 添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息通知给 TxManager 的操作。
3.2.1.3 通知事务组
- 是指在发起方执行完业务代码以后,将发起方执行结果状态通知给 TxManager,TxManager 将根据事务最终状态和事务组的信息来通知相应的参与模块提交或回滚事务,并返回结果给事务发起方
4 TX-LCN 事务模式
- Tx-LCN 5.0 开始支持三种事务模式,分别是:LCN、TCC、TXC 模式。
- 每种模式在实际使用时有着自己对应的注解。
LCN:@LcnTransaction TCC:@TccTransaction TXC:@TxcTransaction 123
4.1 LCN 模式
4.1.1 原理介绍
- LCN 模式是通过代理 JDBC 中 Connection 的方式实现对本地事务的操作,然后在由TxManager 统一协调控制事务。当本地事务提交回滚或者关闭连接时将会执行假操作,该代 理的连接将由 LCN 连接池管理
4.1.2 模式特点
- 该模式对代码的嵌入性低。
- 该模式仅限于本地存在连接对象且可通过连接对象控制事务的模块。
- 该模式下的事务提交与回滚是由本地事务方控制,对于数据一致性上有较高的保障
- 该模式缺陷在于代理的连接需要随事务发起方一同释放连接,增加了连接占用的时间
- 总结:LCN 模式适合能用 JDBC 连接的所有支持事务的数据库
4.2 TCC 事务模式
4.2.1 原理介绍
- TCC 事务机制相对于传统事务机制(X/Open XA Two-Phase-Commit),其特征在于它不依赖资源管理器(RM)对 XA 的支持,而是通过对(由业务系统提供的)业务逻辑的调度来实现分布式事务。主要由三步操作,Try: 尝试执行业务、 Confirm:确认执行业务、 Cancel: 取消执行业务
4.2.2 代码说明
- 每个 TCC 事务处理方法可以额外包含 confirmXxx 和 cancelXxx 的方法(),出现失败问题,需要在 cancel 中通过业务逻辑把改变的数据还原回来
- confirmXxx 和 cancelXxx 两个方法会由 TxManager 进行统一协调调用
- confirmXxx 和 cancelXxx 也可以在@TccTransaction 注解中通过属性明确指定
@TccTransaction public String demo(){ // 正常的 service 方法,也是 Try 尝试执行执行 } public void confirmDemo(){ // 当 demo 方法没有出现异常时执行的方法 // 方法名称必须叫做 confirm+代理方法首字母 } public void cancelDemo(){ // 当 demo 方法出现异常时执行的方法 // 方法名称必须叫做 cancel+代理方法首字母 }
4.2.3 模式特点
- 该模式对代码的嵌入性高,要求每个业务需要写二个以上步骤的操作
- 该模式对有无本地事务控制都可以支持,使用面更广
- 数据一致性控制几乎完全由开发者控制,对业务开发难度要求高
- 总结:Tcc 模式应用于所有不支持 XA 事务的软件。例如:redis,mongodb 等
4.3 TXC 事务模式
4.3.1 原理介绍
- TXC 模式命名来源于淘宝,实现原理是在执行 SQL 之前,先查询 SQL 的影响数据,然后保存执行的 SQL 信息和创建锁。当需要回滚的时候就采用这些记录数据回滚数据库,目前锁实现依赖 redis 分布式锁控制。(在使用 lcn 时必须要配置 redis 参数)
4.3.2 模式特点
- 该模式同样对代码的嵌入性低
- 该模式仅限于对支持 SQL 方式的模块支持
- 该模式由于每次执行 SQL 之前需要先查询影响数据,因此相比 LCN 模式消耗资源与时间要多
- 该模式不会占用数据库的连接资源
- 总结:只能用在支持 SQL 的数据库。对资源消耗较多。建议使用 LCN 模式
5 XA 的两阶段提交方案(数据库支持分布式事务,为什么还用 TX-LCN)
5.1 什么是 XA 协议
XA 协议由 Oracle Tuxedo 首先提出的,并交给 X/Open 组织,作为资源管理器(数据库)与事务管理器的接口标准。目前,Oracle、Informix、DB2 和 Sybase 等各大数据库厂家都提供对 XA 的支持。
- XA 协议采用两阶段提交方式来管理分布式事务。XA 接口提供资源管理器与事务管理器之间进行通信的标准接口。
- XA 就是 X/Open DTP 定义的交易中间件与数据库之间的接口规范(即接口函数),交易中间件用它来通知数据库事务的开始、结束以及提交、回滚等。XA 接口函数由数据库厂商提供。
- X/Open 组织(即现在的 Open Group)定义了分布式事务处理模型。X/Open DTP 模型(1994)包括应用程序(AP)、事务管理器(TM)、资源管理器(RM)、通信资源管理器(CRM)四部分。一般,常见的事务管理器(TM)是交易中间件,常见的资源管理器(RM)是数据库,常见的通信资源管理器(CRM)是消息中间件。
5.2 XA 协议的一阶段提交
- 如果在程序中开启了事务,那么在应用程序发出提交/回滚请求后,数据库执行操作,而后将成功/失败返回给应用程序,程序继续执行
- 一阶段提交协议相对简单。优点也很直观,它不用再与其他的对象交互,节省了判断步骤和时间,所以在性能上是在阶段提交协议中最好的。但缺点也很明显:数据库确认执行事务的时间较长,出问题的可能性就随之增大。如果有多个数据源,一阶段提交协议无法协调他们之间的关系
5.3 XA 协议的二阶段提交
- 在一阶段协议的基础上,有了二阶段协议,二阶段协议的好处是添加了一个管理者角色
很明显,二阶段协议通过将两层变为三层,增加了中间的管理者角色,从而协调多个数据源之间的关系,二阶段提交协议分为两个阶段
- 应用程序调用了事务管理器的提交方法,此后第一阶段分为两个步骤:
- 事务管理器通知参与该事务的各个资源管理器,通知他们开始准备事务。
资源管理器接收到消息后开始准备阶段,写好事务日志并执行事务,但不提交,然后将是否就绪的消息返回给事务管理器(此时已经将事务的大部分事情做完,以后的内容耗时极小)。
- 第二阶段也分为两个步骤:
- 事务管理器在接受各个消息后,开始分析,如果有任意其一失败,则发送回滚命令,否则发送提交命令
- 各个资源管理器接收到命令后,执行(耗时很少),并将提交消息返回给事务管理器
- 事务管理器接受消息后,事务结束,应用程序继续执行
- 为什么要分两步执行?一是因为分两步,就有了事务管理器统一管理的机会;二尽可能晚地提交事务,让事务在提交前尽可能地完成所有能完成的工作,这样,最后的提交阶段将是耗时极短,耗时极短意味着操作失败的可能性也就降低
- 同时,二阶段提交协议为了保证事务的一致性,不管是事务管理器还是各个资源管理器,每执行一步操作,都会记录日志,为出现故障后的恢复准备依据
缺点:
- 二阶段提交协议的存在的弊端是阻塞,因为事务管理器要收集各个资源管理器的响应消息,如果其中一个或多个一直不返回消息,则事务管理器一直等待,应用程序也被阻塞,甚至可能永久阻塞
- 两阶段提交理论的一个广泛工业应用是 XA 协议。目前几乎所有收费的商业数据库都支持 XA 协议。XA 协议已在业界成熟运行数十年,但目前它在互联网海量流量的应用场景中,吞吐量这个瓶颈变得十分致命,因此很少被用到