
第一阶段
业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。核心在于对业务sql进行解析,转换成undolog.
AT模式官方网址
第二阶段
1.分布式事务操作成功,则TC通知RM异步删除undolog
2.分布式事务操作失败,TM向TC发送回滚请求,RM 收到协调器TC发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。
优势
应用层基于SQL解析实现了自动补偿,从而最大程度的降低业务侵入性;
将分布式事务中TC(事务协调者)独立部署,负责事务的注册、回滚;
通过全局锁实现了写隔离与读隔离。
下载seata1.3版本
修改file.conf

修改register.conf

复制数据库创建语句自己创建出来,作为保存相关必要的数据



csdn不让上传文件,我将所有需要的文件打包放入网盘
这里的两个文件也在里面

运行刚才放入的文件
注意nacos这里默认是开启的
sh nacos-config.sh -h 192.168.14.3 -p 8848 -g SEATA_GROUP
可在windows客户端中查看相应刚刚配置的文件
搭建的nacos的ip加上端口号,必须加上/nacos 账号密码均为nacos

需要修改
在刚刚打开的网页中找到并修改记得一定要修改时区
url
jdbc:mysql://192.168.14.53:3306/seata——global?useUnicode=true&serverTimezone=UTC
username,和password改为自己的

启动服务

使用这个命令记得改java的环境变量为java8.
bin/seata-server.sh -p 8091 -n 1
bin/seata-server.sh -p 8092 -n 2

接入微服务应用
业务场景:
用户下单,整个业务逻辑由两个微服务构成:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
调用方法后 通过openfeign调用 stock-app的stock接口 记得检查是否注入
@RestController
public class OrderController {
@Autowired
OrderItemDao orderItemDao;
@Autowired
OrderDao orderDao;
@Autowired
StockClient stockClient;
@PostMapping("/add")
@GlobalTransactional(name = "addOrder")
public String add(@RequestBody Ordering ordering){
String yy = DateUtil.format(DateUtil.date(), "YYYYMMDDHHmmssSSS");
Long aLong = Long.valueOf(yy);
ordering.setId(aLong);
orderDao.addOrderMaster(ordering);
List<OrderingProduct> products = ordering.getProducts();
for(OrderingProduct product : products){
product.setOrderId(aLong);
orderItemDao.addOrderItem(product);
stockClient.upQty(product.getProductId(),product.getQty());
}
return "yes";
}
}
这是调用的方法
@GetMapping("/stock")
@GlobalTransactional(name = "addOrder")
public String upQty(Integer productId,Integer qty){
int a = 5/0;
inventoryDao.updateQty(qty,productId);
inventoryLogDao.log("产品ID为" + productId + "减少数量" + qty);
return null;
}
@GlobalTransactional(name = “addOrder”)
俩个一定要有相同的名字,可以共同成功,共同失败