Seata实战
案例分析
创建订单、修改库存数量、扣减用户余额,分别对应三个微服务:
seata-order-service 订单服务 seata-storage-service 库存服务 seata-account-service 账户服务
三个服务的调用顺序如下:订单服务创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->订单服务修改订单状态
在AT模式中,需要在参与全局事务的数据库中,添加一个undo_log表,每个服务的数据库都要创建一个 undo_log 回滚日志表
CREATE TABLE IF NOT EXISTS `undo_log` ( `branch_id` BIGINT NOT NULL COMMENT 'branch transaction id', `xid` VARCHAR(128) 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';
在全局事务的一阶段中,分支事务在获取到全局锁提交事务时,会释放本地锁和连接资源,并在undo_log表中插入一条数据。重要的是rollback_info,比如在更新一条数据时set money = 97,会查询修改之前该条数据的及修改后的数据状态

在第二阶段中,如果全局事务成功,会收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。
在第二阶段中,如果全局事务失败,会收到 TC 的分支回滚请求,开启一个本地事务,执行如下操作。
通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。
数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需要根据配置策略来做处理,详细的说明在另外的文档中介绍。
根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句。
提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。
t_account表,账户余额有1000
CREATE TABLE t_account( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'id', `user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id', `total` DECIMAL(10,0) DEFAULT NULL COMMENT '总额度', `used` DECIMAL(10,0) DEFAULT NULL COMMENT '已用余额', `residue` DECIMAL(10,0) DEFAULT '0' COMMENT '剩余可用额度' ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO seata_account.t_account(`id`,`user_id`,`total`,`used`,`residue`) VALUES('1','1','1000','0','1000')
t_order表
CREATE TABLE t_order( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, `user_id` BIGINT(11) DEFAULT NULL COMMENT '用户id', `product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id', `count` INT(11) DEFAULT NULL COMMENT '数量', `money` DECIMAL(11,0) DEFAULT NULL COMMENT '金额', `status` INT(1) DEFAULT NULL COMMENT '订单状态:0:创建中; 1:已完结' ) ENGINE=INNODB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;
t_storage表,库存有100
CREATE TABLE t_storage( `id` BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, `product_id` BIGINT(11) DEFAULT NULL COMMENT '产品id', `total` INT(11) DEFAULT NULL COMMENT '总库存', `used` INT(11) DEFAULT NULL COMMENT '已用库存', `residue` INT(11) DEFAULT NULL COMMENT '剩余库存' ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; INSERT INTO seata_storage.t_storage(`id`,`product_id`,`total`,`used`,`residue`) VALUES('1','1','100','0','100');
问题:创建订单->扣减库存->扣减账户完成,由于超时,订单状态没有更新
seata分布式事务
依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> <version>2021.1</version> <exclusions> <exclusion> <groupId>io.seata</groupId> <artifactId>seata-spring-boot-starter</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.seata</groupId> <artifactId>seata-spring-boot-starter</artifactId> <version>1.4.1</version> </dependency>
配置文件
# seata配置
seata.enabled=true
seata.enable-auto-data-source-proxy=true
# config.txt文件中修改的vgroupMapping值
seata.tx-service-group=default
seata.registry.type=nacos
# registry.conf配置文件中 nacos的application名称
seata.registry.nacos.application=seata-server
seata.registry.nacos.server-addr=localhost:8848
seata.registry.nacos.username=nacos
seata.registry.nacos.password=nacos
seata.registry.nacos.namespace=88b8f583-43f9-4272-bd46-78a9f89c56e8
seata.registry.nacos.cluster=default
seata.registry.nacos.group=SEATA_GROUP
seata.config.type=nacos
seata.config.nacos.server-addr=localhost:8848
seata.config.nacos.namespace=88b8f583-43f9-4272-bd46-78a9f89c56e8
seata.config.nacos.group=SEATA_GROUP
seata.config.nacos.username=nacos
seata.config.nacos.password=nacos
开启注解
@EnableAutoDataSourceProxy
业务方法上,添加seata分布式事务注解:@GlobalTransactional
@GlobalTransactional(name = "create-order", rollbackFor = Exception.class) public void create(Order order) { ...
发现seata-order-service会报超时异常,同时seata已经完成数据回滚
参考:
https://www.cnblogs.com/jian0110/p/14762509.html
https://blog.csdn.net/hosaos/article/details/89136666
浙公网安备 33010602011771号