本文只介绍使用,更多资料查看官方文档
创建undo_log表
seata AT模式依赖undo_log表,多个数据源每一个库都需要创建
CREATE TABLE IF NOT EXISTS `undo_log`
(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'increment id',
`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 NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME NOT NULL COMMENT 'modify datetime',
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
seata-server
- 下载seata-server
- 修改conf/registry.conf,将registry.type修改为eureka。即将seata-server注册到eureka
- 启动eureka-server
- 启动seata-server
./bin/seata-server.sh -p 8091
服务结构
支付服务:创建支付信息
账户服务:查询账户余额,扣除账户余额
订单服务:创建订单信息
服务中的配置文件
resources目录下引入registry.conf和file.conf
seata参数配置
server端配置即为seata-server中的配置
client端配置即为代码中的配置
开启数据源自动代理
seata1.1.0版本才能使用,在每一个应用的启动类上添加@EnableAutoDataSourceProxy注解即可
主要业务逻辑
只需要使用一个@GlobalTransactional注解在业务方法上
PayService
@Service
public class PayServiceImpl implements PayService {
@Autowired
private PayDAO payDAO;
@Autowired
private SnowFlake snowFlake;
@Autowired
private AccountFeign accountFeign;
@Autowired
private OrderFeign orderFeign;
@GlobalTransactional
@Override
public String addPay(Long userId, Integer money) {
//添加支付信息
long payId = snowFlake.nextKey();
payDAO.insert(payId, userId, money);
//扣除账号金额
accountFeign.deduction(userId, money);
//创建订单
orderFeign.addOrder(payId);
//模拟异常
// int a = 1/0;
return "success";
}
}
AccountService
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDAO accountDAO;
@Override
public String deduction(Long userId, Integer money) {
int haveMoney = accountDAO.selectMoneyByUserId(userId);
if(haveMoney < money){
throw new RuntimeException("金额不足");
}
accountDAO.updateByUserId(userId, haveMoney - money);
return "success";
}
}
OrderService
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDAO orderDAO;
@Autowired
private SnowFlake snowFlake;
@Override
public String add(Long payId){
orderDAO.insert(snowFlake.nextKey(), payId);
//模拟异常
// int a = 1/0;
return "success";
}
}
测试
curl http://localhost:8081/pay?money=30&userId=1
在每一服务中创建一个异常,任何一个服务出现异常后,所有的服务都会回滚
作者公众号