一、分布式事务
本地事务
在计算机系统中,更多的是通过关系型数据库来控制事务,这是利用数据库本身的事务特性来实现的, 因此叫数据库事务,由于应用主要靠关系数据库来控制事务,而数据库通常和应用在同一个服务器,所以基于关系型数据库的事务又被称为本地事务。
数据库事务的四大特性:ACID
A ( Atomic ):原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失败的情况。
C( Consistency ):一致性,在事务执行前后,数据库的一致性约束没有被破坏。比如:张三向李四转100 元,转账前和转账后的数据是正确状态这叫一致性,如果出现张三转出 100 元,李四账户没有增加
100 元这就出现了数 据错误,就没有达到一致性。
I( Isolation ):隔离性,数据库中的事务一般都是并发的,隔离性是指并发的两个事务的执行互不干扰,一个事务不能看到其他事务的运行过程的中间状态。通过配置事务隔离级别可以比避免脏读、重复读问题。
D( Durability ):持久性,事务完成之后,该事务对数据的更改会持久到数据库,且不会被回滚。数据库事务在实现时会将一次事务的所有操作全部纳入到一个不可分割的执行单元,该执行单元的所有操作要么都成功,要么都失败,只要其中任一操作执行失败,都将导致整个事务的回滚。
分布式事务
随着互联网的快速发展,软件系统由原来的单体应用转变为分布式应用分布式系统会把一个应用系统拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为 分布式事务,例如用户注册送积分事务、创建订单减库存事务,银行转账事务等都是分布式事务。
二、分布式事务理论
CAP理论
CAP理论:一个分布式系统不可能同时满足一致性,可用性和分区容错性这个三个基本需求,最多只能同时满足其中两项
一致性(C):数据在多个副本之间是否能够保持一致的特性。
可用性(A):是指系统提供的服务必须一致处于可用状态,对于每一个用户的请求总是在有限的时间内返回结果,超过时间就认为系统是不可用的
分区容错性(P):分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非整个网络环境都发生故障。
放弃A(CP):其做法是一旦系统遇到网络分区或其他故障时,那受到影响的服务需要等待一定的时间,应用等待期间系统无法对外提供正常的服务,即不可用
放弃C(AP):这里说的放弃一致性,并不是完全不需要数据一致性,是指放弃数据的强一致性,保留数据的最终一致性。
BASE理论
BASE是基本可用,软状态,最终一致性。是对CAP中一致性和可用性权限的结果,是基于CAP定理演化而来的,核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特定,采用适当的方式来使系统达到最终一致性
三、分布式事务解决方案
2PC提交
二阶段提交协议是将事务的提交过程分成提交事务请求和执行事务提交两个阶段进行处理。
阶段1:提交事务请求
- 事务询问:协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应
- 执行事务:各参与者节点执行事务操作,并将Undo和Redo信息记入事务日志中
- 如果参与者成功执事务操作,就反馈给协调者Yes响应,表示事物可以执行,如果没有成功执行事务,就反馈给协调者No响应,表示事务不可以执行
阶段一也被称为投票阶段,即各参与者投票票表明是否可以继续执行接下去的事务提交操作
阶段二:执行事务提交
- 假如协调者从所有的参与者或得反馈都是Yes响应,那么就会执行事务提交。
- 发送提交请求:协调者向所有参与者节点发出Commit请求
- 事务提交:参与者接受到Commit请求后,会正式执行事务提交操作,并在完成提交之后放弃整个事务执行期间占用的事务资源
- 反馈事务提交结果:参与者在完成事物提交之后,向协调者发送ACK消息
- 完成事务:协调者接收到所有参与者反馈的ACK消息后,完成事务
3PC提交
三阶段提,也叫三阶段提交协议,是二阶段提交(2PC)的改进版本。
与两阶段提交不同的是,三阶段提交有两个改动点。引入超时机制。同时在协调者和参与者中都引入超时机制。在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
TCC分布式事务
TCC是服务化的两阶段编程模型,其Try、Confirm、Cancel,3个方法均由业务编码实现,TCC要求每个分支事务实现三个操作:预处理Try,确认Confirm,撤销Cancel。
- Try阶段是做业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的Confirmy一起才能构成一个完整的业务逻辑
- Confirm阶段是做确认提交,Try阶段所有分支事务执行成功后开始执行Confirm,通常情况下,采用TCC则认为Confirm阶段是不会出错的,即:只要Try成功,Confirm一定成功,若Confirm阶段真的出错,需要引入重试机制或人工处理
- Cancel阶段是在业务执行错误需要回滚到状态下执行分支事务的取消,预留资源的释放,通常情况 下,采用TCC则认为Cancel阶段也一定是真功的,若Cance阶段真的出错,需要引入重试机制或人工处理
消息队列实现可靠消息最终一致性
可靠消息最终一致性就是保证消息从生产方经过消息中间件传递到消费方的一致性
RocketMQ主要解决了两个功能:本地事务与消息发送的原子性问题。事务参与方接收消息的可靠性。可靠消息最终一致性事务适合执行周期长且实时性要求不高的场景,引入消息机制后,同步的事务操作变为基于消息执行的异步操作,避免分布式事务中的同步阻塞操作的影响,并实现了两个服务的解耦
所以,消息队列的消息最终一致性并不是普通意义上的分布式事务,而是分开式事务,将事务分成不同的段然后依次执行,只要保证整条链路上的事务最终都执行成功即可(因为mq报错后会重新发送消息)
四、分布式事务中间件
Atomikos
这是一个兼容JTA/JTS标准的分布式事务管理器,可以在JVM中运行,并轻松集成到任何支持JTA标准的环境下。Atomikos支持XA事务模型,能够保证分布式事务在不同数据库和消息服务之间的一致性。基本只能用在单机环境,单机连接多个数据库的情况下保证事务的一致性;
Himly
金融级柔性分布式事务解决方案,一开始只支持TCC模式。当使用TCC
模式的时候,用户根据自身业务需求提供 try
, confirm
, cancel
等三个方法, 并且 confirm
, cancel
方法由自身完成实现,框架只是负责来调用,来达到事务的一致性。后续增加了TAC模式。当用户使用TAC
模式的时候,用户必须使用关系型数据库来进行业务操作,框架会自动生成回滚SQL
, 当业务异常的时候,会执行回滚SQL
来达到事务的一致性。
LCN
LCN框架在2017年6月份发布第一个版本,从开始的1.0,已经发展到了5.0版本。LCN名称是由早期版本的LCN框架命名。5.0以后由于框架兼容了LCN、TCC、TXC三种事务模式,为了避免区分LCN模式,特此将LCN分布式事务改名为TX-LCN分布式事务框架。
TX-LCN定位于一款事务协调性框架,框架其本身并不操作事务,而是基于对事务的协调从而达到事务一致性的效果。
Seata
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案
还有例如EasyTransaction、ByteTCC等。
中间件名称 | Github地址 | star数量 | 简介 |
Seata | https://github.com/seata/seata | 25K | 阿里。目前全网最火最好用的中间件。 |
LCN | https://github.com/codingapi/tx-lcn | 4.2K | CodingApi团队。依赖太多:Redis、Zookeeper、Consul; 停止更新四年(截止2024年5月) |
Hmily | https://github.com/dromara/hmily | 4.1K | 文档完善,SpringCloud与SpringBoot均支持,网上资料多。 7个月前更新(截止2024年5月) |
ByteTCC | https://github.com/liuyangming/ByteTCC | 2.5K | ByteTCC是分布式事务管理器的一个实现,基于尝试确认-取消(TCC)机制。 ByteTCC与JTA兼容,可以与Spring和其他Java容器无缝集成。 停止更新两年(截止2024年5月) |
EasyTransaction | https://github.com/QNJR-GROUP/EasyTransaction | 2.4K | 个人。(资料少、文档少) 停止更新四年(截止2024年5月) |
可以看到了现在基本上是Seata一统江湖的情况。
五、Seata
Seata术语
TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
生命周期
TM要求TC开始新的全局事务。 TC生成表示全局事务的XID。
XID通过微服务的调用链传播。
RM将本地事务注册为XID到TC的相应全局事务的分支。
TM要求TC提交或回滚XID的相应全局事务。
TC在XID的相应全局事务下驱动所有分支事务,以完成分支提交或回滚。
AT模式
两阶段提交协议的演变:
一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
二阶段:提交异步化,非常快速地完成。回滚通过一阶段的回滚日志进行反向补偿。
写隔离
一阶段本地事务提交前,需要确保先拿到 全局锁 。
拿不到 全局锁,不能提交本地事务。
拿 全局锁 的尝试被限制在一定范围内,超出范围将放弃,并回滚本地事务,释放本地锁。
流程图:
两个全局事务 tx1 和 tx2,分别对 a 表的 m 字段进行更新操作,m 的初始值 1000。
tx1 先开始,开启本地事务,拿到本地锁,更新操作 m = 1000 - 100 = 900。本地事务提交前,先拿到该记录的 全局锁 ,本地提交释放本地锁。 tx2 后开始,开启本地事务,拿到本地锁,更新操作 m = 900 - 100 = 800。本地事务提交前,尝试拿该记录的 全局锁 ,tx1 全局提交前,该记录的全局锁被 tx1 持有,tx2 需要重试等待 全局锁 。
TCC模式
TCC 模式,不依赖于底层数据资源的事务支持:
一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
二阶段 commit 行为:调用 自定义 的 commit 逻辑。
二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。
Saga 模式
Saga模式是SEATA提供的长事务解决方案,在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现
关于使用示例,请根据版本参考官网的文档
https://seata.apache.org/zh-cn/
参考:
分布式事务--TCC的中间件--选型/对比-CSDN博客
哔哩哔哩:1 阿里分布式事务框架Seata简介_哔哩哔哩_bilibili