本篇文章为大家展示了seata中如何使用AT和TCC模式,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
图片来自 Seata解析-TM、RM、TC交互流程梳理
维护全局和分支事务的状态,驱动全局事务提交或回滚。
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
基于支持本地 ACID 事务的关系型数据库。
Java 应用,通过 JDBC 访问数据库。
两阶段提交协议的演变:
一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
二阶段:
提交异步化,非常快速地完成。
回滚通过一阶段的回滚日志进行反向补偿。
一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:
一阶段 prepare 行为
二阶段 commit 或 rollback 行为
TCC 模式,不依赖于底层数据资源的事务支持:
一阶段 prepare 行为:调用 自定义 的 prepare 逻辑。
二阶段 commit 行为:调用 自定义 的 commit 逻辑。
二阶段 rollback 行为:调用 自定义 的 rollback 逻辑。
所谓 TCC 模式,是指支持把 自定义 的分支事务纳入到全局事务的管理中。
参照官网部署教程,启动成功后可以看到这句 Server started, listen port: 8091
,注意这个端口不是用来通过http访问的, 这个端口是用来协调应用分布式事务的,直接通过浏览器访问会报错。
SLF4J: A number (18) of logging calls during the initialization phase have been intercepted and are SLF4J: now being replayed. These are subject to the filtering rules of the underlying logging system. SLF4J: See also http://www.slf4j.org/codes.html#replay 09:54:04.048 INFO --- [ main] io.seata.config.FileConfiguration : The file name of the operation is registry 09:54:04.055 INFO --- [ main] io.seata.config.FileConfiguration : The configuration file used is C:\Server\seata-server-1.4.2\conf\registry.conf 09:54:04.119 INFO --- [ main] io.seata.config.FileConfiguration : The file name of the operation is file.conf 09:54:04.119 INFO --- [ main] io.seata.config.FileConfiguration : The configuration file used is C:\Server\seata-server-1.4.2\conf\file.conf 09:54:06.578 INFO --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited 09:54:07.304 INFO --- [ main] i.s.core.rpc.netty.NettyServerBootstrap : Server started, listen port: 8091
<!-- 分布式事务seata --> <dependency> <groupid>com.alibaba.cloud</groupid> <artifactid>spring-cloud-starter-alibaba-seata</artifactid> </dependency> <!-- 序列化方式选择的kryo, 在使用jackson和fastjson时,对时间的序列化一直出问题 --> <dependency> <groupid>de.javakaffee</groupid> <artifactid>kryo-serializers</artifactid> <version>${kryo.serializers.version}</version> </dependency>
seata: service: # TC服务列表 仅注册中心为file时使用 grouplist: default : seata.server.cn:8091 # 事务群组, service-goods-center为分组,配置项值为TC集群名 vgroup-mapping: service-goods-center: default # 全局事务开关,默认false。false为开启,true为关闭 disable-global-transaction: false # 视作分名 tx-service-group: service-goods-center client: undo: # undolog的序列化方式, AT模式需要配置,因为AT模式数据库会有undo-log表 log-serialization: kryo
访问 seata数据库脚本 链接,找到对应版本和对应数据库类型的SQL脚本,在业务系统创建出来undo-log
表。
1.3.0版本
CREATE TABLE IF NOT EXISTS `undo_log` ( `branch_id` BIGINT(20) NOT NULL COMMENT 'branch transaction id', `xid` VARCHAR(100) NOT NULL COMMENT 'global transaction id', `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization', `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
只需要在TM端服务方法上加上@GlobalTransactional
注解,被调用RM端方法可以不用显式的声明@GlobalTransactional
注解
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public String insert() { service.insert(); //放开以下注解抛出异常 //throw new RuntimeException("服务AT测试回滚"); return "success"; }
@LocalTCC
一定需要注解在接口上,否则不生效,此接口可以是寻常的业务接口,只要实现了TCC的两阶段提交对应方法便可,TCC相关注解如下:
@LocalTCC
适用于SpringCloud+Feign模式下的TCC
@TwoPhaseBusinessAction
注解try方法,其中name为当前tcc方法的bean名称,写方法名便可(全局唯一),commitMethod指向提交方法,rollbackMethod指向事务回滚方法。指定好三个方法之后,seata会根据全局事务的成功或失败,去帮我们自动调用提交方法或者回滚方法。
@BusinessActionContextParameter
注解可以将参数传递到二阶段(commitMethod/rollbackMethod)的方法。
BusinessActionContext
便是指TCC事务上下文
/** * 这里定义tcc的接口 * 这些一定要定义在接口上 * 我们使用springCloud的远程调用 * 那么这里使用LocalTCC便可 * * @author tanzj */ @LocalTCC public interface TccService { /** * 定义两阶段提交 * name = 该tcc的bean名称,全局唯一 * commitMethod = commit 为二阶段确认方法 * rollbackMethod = rollback 为二阶段取消方法 * BusinessActionContextParameter注解 传递参数到二阶段中 * */ @TwoPhaseBusinessAction(name = "insert", commitMethod = "commitTcc", rollbackMethod = "cancel") String insert( @BusinessActionContextParameter(paramName = "params") Map<string, string> params ); /** * 确认方法、可以另命名,但要保证与commitMethod一致 * context可以传递try方法的参数 * 参数是固定的, 不可以增加或减少, */ boolean commitTcc(BusinessActionContext context); /** * 二阶段取消方法 * 参数是固定的, 不可以增加或减少 */ boolean cancel(BusinessActionContext context); }
在try方法中使用@Transational
可以直接通过spring事务回滚关系型数据库中的操作,而非关系型数据库等中间件的回滚操作可以交给rollbackMethod方法处理。
使用context.getActionContext("params")便可以得到一阶段try中定义的参数,在二阶段对此参数进行业务回滚操作。
**注意1:**此处亦不可以捕获异常(同理切面处理异常),否则TCC将识别该操作为成功,二阶段直接执行commitMethod。
**注意2:**TCC模式要开发者自行保证幂等和事务防悬挂
调用代码
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public String insert() { log.info("xid = " + RootContext.getXID()); //todo 实际的操作,或操作MQ、redis等 tccDAO.insert(new HashMap<>()); //放开以下注解抛出异常 //throw new RuntimeException("服务tcc测试回滚"); return "success"; }
也没别的,默认使用的就是AT事务,别在同一个接口方法上添加TCC注解就行,可以通过AT方法嵌套TCC方法,注意不要通过this.xx()调用,这样会无法应用代理的增强。
mybatis-plus
出现问题,解决方案透过源码解决SeataAT模式整合Mybatis-Plus失去MP特性的问题</string,>
上述内容就是seata中如何使用AT和TCC模式,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。