Seata客户端搭建
- 搭建两个服务,分别实现数据库操作
order 服务
@RestController
@RefreshScope
public class NacosOrderController {
@Resource
private OrderMapper orderMapper;
@Autowired
private StockService stockService;
@GetMapping(value = "order")
@GlobalTransactional
public String doOrder() {
Order order = new Order();
order.setOid((long) (Math.random() * (10000000)));
orderMapper.insertOrder(order);
stockService.reduce();
int a = 1 / 0;
return "下单成功";
}
}
<insert id="insertOrder" parameterType="com.example.orderseata.domain.Order">
insert into `order` (oid)
values (#{oid})
</insert>
stock服务
@RestController
@RefreshScope
public class NacosStockController {
@Resource
private StockMapper stockMapper;
@GetMapping(value = "reduce")
@GlobalTransactional
public String reduce() {
stockMapper.reduce();
return "下单成功";
}
}
<update id="reduce">
update stock
set num = num - 1
where cid = 1
</update>
- 添加seata依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-seata</artifactId>
</dependency>
- 给涉及的数据库添加undolog表
我们这里是stock库和order库
DROP TABLE IF EXISTS `undo_log`;
CREATE TABLE `undo_log` (
`branch_id` bigint(20) NOT NULL COMMENT '分支事务ID',
`xid` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '全局事务ID',
`context` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '上下文',
`rollback_info` longblob NOT NULL COMMENT '回滚信息',
`log_status` int(11) NOT NULL COMMENT '状态,0正常,1全局已完成',
`log_created` datetime(6) NOT NULL COMMENT '创建时间',
`log_modified` datetime(6) NOT NULL COMMENT '修改时间',
UNIQUE INDEX `ux_undo_log`(`xid`, `branch_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'AT transaction mode undo table' ROW_FORMAT = Compact;
- 配置seata,注意事务分组配置
seata:
registry: # 注册中心
type: nacos
nacos:
server-addr: 127.0.0.1:8848
application: seata-server # 默认配置
username: nacos
password: nacos
group: SEATA_GROUP # 默认配置
config: # 配置中心,读取client配置
type: nacos
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
group: SEATA_GROUP # 默认配置
enabled: true
tx-service-group: my_test_tx_group # 搭建service端时 service.vgroupMapping配置的时什么就是什么
-
修改事务注解为@GlobalTransactional
-
调用接口查看事务是否生效
-
断点查看事务相关表,解析原理
seata_server库中gloab_table表,全局事务
branch_table表,分支事务
undo_log表,用于事务回滚
查看rollback_info字段SELECT CONVERT(t.rollback_info USING utf8) FROM `undo_log` t
{"@class":"io.seata.rm.datasource.undo.BranchUndoLog","xid":"192.168.137.1:8091:337579209592410112","branchId":337579232245846017,"sqlUndoLogs":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.undo.SQLUndoLog","sqlType":"INSERT","tableName":"`order`","beforeImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords$EmptyTableRecords","tableName":"order","rows":["java.util.ArrayList",[]]},"afterImage":{"@class":"io.seata.rm.datasource.sql.struct.TableRecords","tableName":"order","rows":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Row","fields":["java.util.ArrayList",[{"@class":"io.seata.rm.datasource.sql.struct.Field","name":"oid","keyType":"PRIMARY_KEY","type":-5,"value":["java.lang.Long",7422002]}]]}]]}}]]}
-
完整的application.yaml配置
server:
port: 8031
spring:
application:
# 会自动根据服务名拉取dataid对应的配置文件。如果dataid跟服务名不一致,就需要手动指定dataid
name: seata-nacos-order
datasource:
url: jdbc:mysql://127.0.0.1:3306/order?characterEncoding=utf-8&serverTimezone=UTC
username: root #数据库用户
password: Huawei@123# #数据库密码
driverClassName: com.mysql.cj.jdbc.Driver
cloud:
nacos:
discovery:
server-addr: http://127.0.0.1:8848
username: nacos
password: nacos
mybatis:
mapper-locations: classpath:mapper/*.xml
seata:
registry: # 注册中心
type: nacos
nacos:
server-addr: 127.0.0.1:8848
application: seata-server # 默认配置
username: nacos
password: nacos
group: SEATA_GROUP # 默认配置
config: # 配置中心,读取client配置
type: nacos
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
group: SEATA_GROUP # 默认配置
完整的bootstrap.yaml配置
spring:
application:
# 会自动根据服务名拉去dataid对应的配置文件,如果dataid和服务名不一致,就需要手动指定dataid
name: nacos-order
cloud:
nacos:
config:
server-addr: http://127.0.0.1:8848
username: nacos
password: nacos
namespace: dev
shared-configs:
#data-id 必须添加配置格式后缀
- data-id: order-shared-config.properties
refresh: true
extension-configs[0]:
data-id: order-extension-config.properties
refresh: true