seata 分布式事务 -- AT模式

模块组成:


1)TM:事务发起者。定义事务的边界,负责告知 TC,分布式事务的开始,提交,回滚。

2)RM:资源管理者。管理每个分支事务的资源,每一个 RM 都会作为一个分支事务注册在 TC。

3)TC :事务协调者。负责我们的事务ID的生成,事务注册、提交、回滚等。


AT模式的前提是基于支持本地 ACID 事务的关系型数据库和Java应用基于JDBC访问数据库。

AT模式是二阶段提交协议的演变:

一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。

二阶段:commit异步化快速完成;rollback通过一阶段的回滚日志进行反向补偿。


读写隔离:

写隔离保证是通过全局锁来保证的,一阶段事务提交前必须要拿到全局锁,否则不能提交本地事务,

获取全局锁过程中不能无限等待,超时后放弃,并回滚本地事务,释放本地锁(避免产生死锁)。

 


举例:

假设 tx1 先拿到本地锁,执行流程:


结果:
tx1 此时只能等 (等 tx2 获取全局锁超时,回滚 tx2 第二步执行的Sql,释放掉本地锁)
然后再获取本地锁回滚 第一步 执行的Sql.

 

 


工作机制:

一阶段:

解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = 'TXC')等相关的信息。
查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。
执行业务 SQL:执行业务更新SQL。
查询后镜像:根据前镜像的结果,通过 主键 定位数据。
插入回滚日志:把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中。
提交前,向 TC 注册分支:申请 product 表中,主键值等于 1 的记录的 全局锁 。
本地事务提交:业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。
将本地事务提交的结果上报给 TC。
一阶段在分支事务提交前向TC注册分支,进行一次通信。

二阶段-回滚:

收到 TC 的分支回滚请求,开启一个本地事务,执行如下操作。
通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。
数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理,详细的说明在另外的文档中介绍。
根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句。
提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。

二阶段-提交:

收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。
异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。


简单理解:

一个典型的事务过程:

1. TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。

2. XID 在微服务调用链路的上下文中传播。

3. RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖。

4. TM 向 TC 发起针对 XID 的全局提交或回滚决议。

5. TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。

 

AT 模 式 需 要 用 到 的 数 据 库 表 :

创建 undo_log 表, sql语句 :

DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8;

 

原文地址:https://www.cnblogs.com/lifan12589/p/14780927.html