seata
分布式事务解决方案 官网 : seata.io
事务模式:
名词
- TC : transaction coordinator 事务协调者
维护全局事务 和 分支事务的状态,驱动全局事务提交或者回滚 - TM : transaction manager 事务管理器
定义全局事务的范围 - RM : resource manager 资源管理器
管理分支事务处理的资源,,与TC交谈,,注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚
AT模式
两阶段提交协议:
-
一阶段 :业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
- 解析SQL
- 根据解析的条件,得到
前镜像
(更新之前的数据) - 执行业务sql
- 根据主键,查找
后镜像
(更新之后的数据) - 插入回滚日志
undo_log
- 提交前,向TC注册分支,,给当前记录开启
全局锁
- 本地事务提交
- 将本地事务提交结果上报给TC
-
二阶段:
- 提交异步化,非常快速地完成。
- 回滚通过一阶段的回滚日志进行反向补偿。
- 收到TC的分支回滚请求,开启一个本地事务
- 通过
XID
和Branch ID
定位当前 undo_log 记录 - 将当前数据 和 undo_log中后镜像,做对比,如果数据不同,说明别的线程操作过了,,这种情况,需要根据配置策略来处理
- 根据undo_log前镜像,进行回滚
- 提交本地事务,,并将本地事务执行结果,上报给TC
官网例子
配置文件:
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
# 事务分组信息,,和 file.conf中一致
seata.tx-service-group=my_test_tx_group
# 114.132.51.96服务器上的seata 8091: seata通讯端口
seata.service.grouplist.114.132.51.96=8091
@RestControllerAdvice
public class GlobalException {
@ExceptionHandler(RuntimeException.class)
// 将错误抛出去 ,不能处理掉
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public RespBean runtimeException(RuntimeException e){
return RespBean.error(e.getMessage());
}
}
问题:
- 公共模块定义的全局异常失效
在其他模块引用的时候,@SpringbootApplication 扫当前包,,公共包引入进来的路径,可能扫不到
@SpringBootApplication(scanBasePackages = {"com.cj.business","com.cj.common"})
github:https://github.com/water-kid/seata
若依中@DataSource多数据源事务处理
@Transactional
只能处理一个数据源,,添加@Transational 之后,@DataSource 注解不能切换到别的 数据库,,只会在同一个数据源中 操作
springboot引入seata:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
使用seata-at模式: 在数据库中创建 undo_log
表
添加如下配置:
因为 registry.conf
配置的 eureka,,需要启动一个 eureka
seata中的数据源是 DataSourceProxy
,
在配置多数据源的时候 将 DataSource 换成 DataSourceProxy
使用: @GlobalTransactional 。。 操作多个数据源
github:https://github.com/water-kid/ry/tree/master/datasource