这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战
Seata配置有几个配置项需要注意:
- seata.support.spring.datasource-autoproxy:true属性表示数据源自动代理开关,在order-service、account-service、repo-service中设置为true,在rest-web中设置为false,因为该项目并没有访问数据源,不需要代理
- 如果注册中心为file,seata.service.grouplist需要填写Seata服务端连接地址,在默认情况下,注册中心为file,如果需要从注册中心上进行服务发现,可增加配置如下:
seata:
registry:
type: nacos
nacos:
cluster: default
server-addr: 192.168.216.128:8848
复制代码
- tx-service-group表示指定服务所属的事务分组,如果没有执行,默认使用spring.application.name加上-seata-service-group,需要注意这两项配置必须配置一项,否则会报错。
添加回滚日志表
分别在3个数据库seata-account、seata-repo、seata-order中添加一张回滚日志表,用于记录每个数据库表操作的回滚日志,当某个服务的事务出现异常时会根据该日志进行回滚。
CREATE TABLE undo_log(
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '' ,
branch_id bigint(20) COMMENT '' ,
xid VARCHAR(200) COMMENT '' ,
context VARCHAR(250) COMMENT '' ,
rollback_info longblob COMMENT '' ,
log_status int(11) COMMENT '' ,
log_created DATETIME COMMENT '' ,
log_modified DATETIME COMMENT '' ,
PRIMARY KEY (id)
UNIQUE KEY 'ux_undo_log'('xid,'branch_id')
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT = '回滚日志表';
复制代码
rest-web增加全局事务控制
修改rest-web项目的RestOrderServiceImpl,需要做以下两个操作:
- 增加@GlobalTransactional全局事务注解
- 模拟一个异常处理,当商品编号等于某个指定的值时抛出异常,触发整个事务的回滚。
@Slf4j
@Service
public class RestOrderServiceImpl implements IRestOrderService{
@Reference
private IRepoService repoService;
@Reference
private IOrderService orderService;
@Override
@GlobalTransactional(timeoutMills=300000,name="rest-web")
public AjaxResult handleBusiness(OrderReq orderReq) throw Exception{
log.info("开始全局事务:xid={}",RootContext.getIp());
log.info("开始订单:"+orderReq);
ProductDto productDto = new ProductDto();
productDto.setProductCode(orderReq.getProductCode());
productDto.setCount(orderReq.getCount());
AjaxResult ajaxResult = repoService.decreaseRepo(productDto);
//创建订单
OrderDto orderDto = new OrderDto();
orderDto.setUserId(orderReq.getUserId());
orderDto.setOrderAmount(orderReq.getAmount());
orderDto.setOrderCount(orderReq.getCount());
orderDto.setProductCode(orderReq.getProductCode());
AjaxResult orderResult = orderServce.createOrder(orderDto);
if(orderReq.getProductCode().equals("20211113")){
throw new Exception("触发异常");
}
AjaxResult result = new AjaxResult();
result.put("data",orderResult.getData());
return result;
}
}
复制代码
在异常触发的位置来看,如果没有引入分布式事务,即使出现了异常,由于库存扣减、订单创建、账户资金扣减等操作已经生效,所以数据无法被回滚,而在引入seata后,在异常出现后会触发各个事务分支的数据回滚,保证数据的正确性,如果配置正常,能完成事务回滚操作。
近期评论