分布式事务
Seata
Apache Seata(incubating) 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
解决分布式事务,各个子事务之间必须能够感知到彼此的事务状态,才能保证一致
Seata事务中有三个重要的角色
- TC(Transaction Coordinator)-事务协调者:维护全局和分支的事务状态,协调全局事务提交或回滚
- TM(Transaction Manager)-事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务
- RM(Resource Manager)-资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态
部署TC服务
Seata支持多钟存储模式,但考虑到数据持久话的需要,我们一般选择基于数据库存储
这里seata的搭建需要大量的配置,他本质上是一个springboot的服务,通过application或者nacos进行配置都可。其中,数据持久化也可以选择基于Redis或者MySQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| services: seata: image: seataio/seata-server:1.5.2 container_name: seata ports: - "8099:8099" - "7099:7099" volumes: - ./seata:/seata-server/resources privileged: true restart: no networks: - my_app_network
networks: my_app_network: external: true
|
微服务中集成Seata
在微服务中引入Seata依赖
1 2 3 4
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency>
|
在微服务中配置TC地址,在这里,Seata可能会被配置成集群注册到Nacos中,所以让微服务通过Nacos来获取TC服务的地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| seata: registry: type: nacos nacos: server-addr: localhost:8848 namespace: "" group: DEFAULT_GROUP application: seata-server username: nacos password: nacos tx-service-group: hmall service: vgroup-mapping: hmall: "default"
|
这里的配置文件可以抽出来在Nacos做共享配置文件
XA模式
事务具有强一致性,所有的分支事务仅执行不提交,等所有的分支事务执行完成后一起提交
常用数据库都支持,实现简单,并且没有代码侵入
性能恩差,依赖关系行数据库实现事务
开启方法
在配置文件中开启XA
1 2
| seata: data-source-proxy-mode: XA
|
在事务的入口方法处添加@GlobalTransactional注解
1 2 3 4
| @Override @GlobalTransactional public Long createOrder(OrderFormDTO orderFormDTO) { }
|
分支事务也要加上@Transactional注解以便回滚
AT模式
Seata主推的是AT模式,AT模式同样是分阶段提交的事务模型,不过弥补了XA模型中资源锁定周期过长的缺陷
XA模式是直接上一把物理排他锁,在事务过程中,任何请求都阻塞(包括读写)
AT模式是分支事务上物理锁,释放的很快,全局事务上一把逻辑锁(全局写锁)
虽然其他写的请求无法正常执行,但不影响读的请求
这也意味着在事务执行期间,AT模式会出现“脏读”问题,但最终一致性可以得到保障
开启AT模式
AT模式需要为每一个微服务提供undo_log表
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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, `ext` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
在配置文件中开启AT,但这个属性的默认值就是AT(约定大于配置)
1 2
| seata: data-source-proxy-mode: AT
|
同XA模式,在事务的入口方法处添加@GlobalTransactional注解
分支事务也要加上@Transactional注解以便回滚