正文
:如果同时发起两个转账事务,应该确保每个事务只访问自己的数据,不会互相干扰;
持久性
:一旦转账完成,更改数据的事务就必须写入磁盘,保证即使系统崩溃或重启后,这些数据仍然是可用的;
数据库事务绝对是程序员的一大利器,但由于各种原因,这把利器离我们越来越远:
1.负载的挑战:随着业务的快速增长,数据库中的数据量或负载也会达到单一实例的上线,此时,我们:
-
垂直拆分:将不同的表放到不同的数据库实例,比如拆分出 User 实例,Order 实例;
-
水平拆分:数据量超过单表最大容量时,将数据分拆到不同的数据库,比如 Order-1 实例、Order-2 实例;
-
5.微服务的挑战:微服务已经成为系统的事实架构,特别是 Spring Boot 和 Spring Cloud 的流行:
-
微服务的“自治”要求每个微服务都应该有自己的独立数据存储,避免与其他服务共享数据存储,从而降低服务之间的耦合性;
-
微服务间通过服务发现、负载均衡等方式,将服务之间的关系解耦,从而使得每个服务都具备独立的自治性;
不管触发哪一种条件,都会产生跨数据库事务,从而增加系统设计的难度。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
-
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
-
视频教程:https://doc.iocoder.cn/video/
针对该问题前人已经提出来多种应对方案,特别是关系型数据库。
熟悉 MySQL 实现的伙伴知道,MySQL 是通过 Redo log 和 Undo log 来实现事务一致性的:
-
Redo Log:Redo Log 记录了事务对数据库所作的修改,包括插入、更新、删除等操作,它在事务提交前就被写入磁盘。如果出现故障导致系统崩溃,MySQL 会从 Redo Log 中恢复数据;
-
Undo Log:Undo Log 记录了事务对数据库所作的修改的「前置操作」,并且在事务回滚时用来撤销事务所做的修改。当事务执行更新时,MySQL 会先将修改前的数据存储到 Undo Log 中,当事务需要回滚时,MySQL 会根据 Undo Log 中的记录将数据还原为修改前的状态。
具体的如下图所示:
从图中可知:
1.每一个 DML 语句都会为其生成对应的 Redo log 和 Undo log。
-
-
2.事务提交应用全部 Redolog 以持久化正向修改;
3.事务回滚应用全部 Undolog 以逆向恢复;
其中,可以看出存在两个核心流程:
-
向前补偿:redo log 记录了事务执行的过程,以及事务提交前的数据修改,可以通过重做日志来恢复数据,实现向前补偿;
-
向后补偿:undo log 记录了事务执行过程中对数据的修改,可以用于回滚事务,实现向后补偿;
除了两种补偿机制外,还涉及一个重要的组件“补偿管理器”,用于对补偿机制进行统一协调。
2PC(Two-Phase Commit)和XA是分布式事务中常用的协议和接口:
-
2PC是分布式事务协议,用于在分布式系统中协调多个参与者的事务提交或回滚。它包括两个阶段:准备阶段和提交阶段,参与者在准备阶段告知协调者它们是否可以正常提交,如果都能正常提交,则在提交阶段所有参与者都提交事务。如果有一个参与者无法正常提交,则所有参与者都需要回滚;
-
XA是一组应用程序接口(API),它使应用程序能够参与分布式事务,并与事务管理器协同工作,以保证事务的一致性。XA接口包括三个接口:XA Transactions、XA Resource、XA Resource Manager,用于实现分布式事务的协调和管理。
MySQL 采用了两阶段提交(Two-Phase Commit,简称 2PC)协议,保证 Redolog 和 Binlog 间的数据一致性,确保事务在所有相关节点(包括 Redolog 和 Binlog)执行的情况下,要么全部提交成功,要么全部回滚失败。
2PC只能应用于两个事务参与者的场景,而XA可以应用于多个事务参与者的场景,具体如图所示:
XA 定义了一组接口:
-
XA资源管理器(XA Resource Manager,RM):用于管理分布式事务的资源,如数据库、消息队列等;
-
XA事务管理器(XA Transaction Manager,TM):用于协调各个资源管理器的事务处理;
-
XA接口:XA接口允许应用程序参与到分布式事务的协调中,包括开始、提交或回滚事务等操作;
对应的事务提交和回滚流程如下:
-
应用程序通过XA接口开始一个分布式事务,XA事务管理器为该事务分配一个唯一的全局事务ID;
-
应用程序使用XA接口将某些操作注册为分布式事务的一部分,这些操作可以涉及多个XA资源管理器;
-
当应用程序执行到提交事务的代码时,XA事务管理器先协调各个XA资源管理器,检查这些资源管理器是否都能够提交事务;
-
如果所有的资源管理器都能够提交事务,则XA事务管理器向各个资源管理器发送提交事务的请求,并等待它们的响应;
-
如果其中有任何一个资源管理器不能提交事务,则XA事务管理器向各个资源管理器发送回滚事务的请求,并等待它们的响应;
-
当所有的资源管理器都响应提交或回滚事务的请求后,XA事务管理器将事务的状态(提交或回滚)通知给应用程序,并释放资源。
2PC (包括升级后的 3PC),在事务执行的整个流程中都需要对资源进行锁定,在分布式环境下将大幅增加系统响应时间,降低整个系统的吞吐,在实际工作中使用的非常少。
TCC 是实现分布式事务解决方案的一种有效方法,更是真正应用于实际工作的一大解决方案。
TCC (try-confirm-cancel) 是一种分布式事务解决方案,它将一个分布式事务拆分成三个过程:
-
Try 操作:尝试执行分布式事务中的操作,检查所有参与方是否准备好执行事务。如果准备好,则锁定资源,等待确认或取消操作;
-
Confirm 操作:确认执行分布式事务中的操作,提交所有参与方的操作。如果有任何错误,则回滚所有操作并释放锁定的资源;
-
Cancel 操作:取消执行分布式事务中的操作,回滚所有参与方的操作并释放锁定的资源;
TCC 的操作流程如下:
-
应用程序向协调者请求分布式事务,并传输所有需要执行的操作;
-
协调者根据 TCC 的分布式事务处理策略创建一个唯一的分布式事务 ID,并将它分配给每个参与方;
-
各参与方执行 Try 操作,并锁定需要访问的资源;
-
协调者检查所有参与方是否准备好执行操作,如果所有参与方都准备好,则进入 Confirm 阶段;
-
Confirm 阶段中,各参与方确认执行操作,并将结果提交给协调者;
-
如果有任何错误,协调者将回滚所有操作并释放锁定的资源。否则,所有参与方之间的事务将得到确认执行,释放资源并关闭事务;
-
如果任何参与方在 Try 阶段失败,则进入 Cancel 阶段;
-
Cancel 阶段中,各参与方撤销所有操作并释放锁定的资源;
-
TCC 是一种补偿型事务机制,通过人工干预来处理异常,本身具备极佳的灵活性,适用于各种不同类型的应用场景。
看了不少一致性解决方案,不知道有没有发现一些规律?
核心组件基本一致:
-
应用程序:简单理解为开发的应用系统,借助事务管理器和资源管理的的能力,完成事务一致性保障;
-
事务管理器:事务的协调者,接收应用程序的请求,对多个资源管理器进行协调,共同完成正向补偿和逆向补偿;
-
资源管理器:单一资源管理者,对外提供正向补偿接口和逆向补充接口,供应用程序和事务管理器使用;
核心流程基本一致:
-
正向补偿:应用流程向前推进,最终从一个状态变化为另一个状态;
-
逆向补偿:应用流程向后推进,将所有操作进行回滚,使其恢复到前一状态;
简单来说:事务一致性就是通过协调各个参与节点来实现分布式事务的提交或回滚,确保所有涉及到的操作,要么全部执行成功,要么全部不执行。不同的实现方式只是不同的工具,其实现思路基本一致。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
-
项目地址:https://github.com/YunaiV/yudao-cloud