文章目录
- 一、Seata 介绍
- 二、Seata Server 的搭建
- 三、Seata Client 的使用
一、Seata 介绍
单体应用被拆分成微服务应用后,原本的各个模块变成了独立的应用,分别使用不同的数据源。当业务操作调用多个不同的微服务时,此时每个服务内部的数据一致性由本地事务来保证,但是全局数据一致性问题没法保证,这就是我们需要面临的分布式事务问题
SpringCloud Alibaba Seata
是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。Seata
将为用户提供了AT
、TCC
、SAGA
和 XA
事务模式,为用户打造一站式的分布式解决方案。
Seata 概念介绍
名称 | 介绍 |
---|---|
Transaction ID | 全局唯一的事务ID |
TC | 事务协调者,维护全局和分支事务的状态,驱动全局事务提交或回滚。 |
TM | 事务管理器,定义全局的事务范围:开启全局事务、提交或回滚全局事务。 |
RM | 资源管理器,管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务的提交或回滚。 |
Seata 分布式事务处理过程:
TM
向TC
申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID
;XID
在微服务调用链路的上下文中传播;RM
向TC
注册分支事务,将其纳入XID
对应全局事务的管辖;TM
向TC
发起针对XID
的全局提交或回滚决议;TC
调度XID
下管辖的全部分支事务完成提交或回滚请求。
二、Seata Server 的搭建
① 下载seata-server-1.1.0
② 修改配置文件file.conf
service {vgroupMapping.my_test_tx_group = "fsp_tx_group"default.grouplist = "127.0.0.1:8091"enableDegrade = falsedisableGlobalTransaction = false
}
store {mode = "db"file {dir = "sessionStore"maxBranchSessionSize = 16384maxGlobalSessionSize = 512fileWriteBufferCacheSize = 16384sessionReloadReadSize = 100flushDiskMode = async}db {datasource = "dbcp"dbType = "mysql"driverClassName = "com.mysql.jdbc.Driver"url = "jdbc:mysql://192.168.182.200:3306/seata"user = "root"password = "1234"minConn = 1maxConn = 10globalTable = "global_table"branchTable = "branch_table"lockTable = "lock_table"queryLimit = 100}
}
③ 修改配置文件registry.conf
registry {type = "nacos"nacos {serverAddr = "localhost:8848"namespace = ""cluster = "default"}}config {type = "nacos"nacos {serverAddr = "localhost:8848"namespace = ""}}
④ 新建数据库seata
-- the table to store GlobalSession data
drop table if exists `global_table`;
create table `global_table` (`xid` varchar(128) not null,`transaction_id` bigint,`status` tinyint not null,`application_id` varchar(32),`transaction_service_group` varchar(32),`transaction_name` varchar(128),`timeout` int,`begin_time` bigint,`application_data` varchar(2000),`gmt_create` datetime,`gmt_modified` datetime,primary key (`xid`),key `idx_gmt_modified_status` (`gmt_modified`, `status`),key `idx_transaction_id` (`transaction_id`)
);-- the table to store BranchSession data
drop table if exists `branch_table`;
create table `branch_table` (`branch_id` bigint not null,`xid` varchar(128) not null,`transaction_id` bigint ,`resource_group_id` varchar(32),`resource_id` varchar(256) ,`lock_key` varchar(128) ,`branch_type` varchar(8) ,`status` tinyint,`client_id` varchar(64),`application_data` varchar(2000),`gmt_create` datetime,`gmt_modified` datetime,primary key (`branch_id`),key `idx_xid` (`xid`)
);-- the table to store lock data
drop table if exists `lock_table`;
create table `lock_table` (`row_key` varchar(128) not null,`xid` varchar(96),`transaction_id` long ,`branch_id` long,`resource_id` varchar(256) ,`table_name` varchar(32) ,`pk` varchar(36) ,`gmt_create` datetime ,`gmt_modified` datetime,primary key(`row_key`)
);
⑤启动seata-server
点击seata-server.bat
三、Seata Client 的使用
① 引入对应版本的seata
依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><groupId>io.seata</groupId><artifactId>seata-all</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>0.9.0</version></dependency>
② 添加配置文件项
spring:cloud:alibaba:seata:# 自定义事务组名称需要与seata-server中的对应tx-service-group: fsp_tx_group
③ 复制file.conf
和registry.conf
文件到resources
目录下
④ service
代码添加注解@GlobalTransactional
@GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)
⑤ 使用seata
对数据源进行代理
/**** 使用Seata对数据源进行代理*/
@Configuration
public class DatasourceProxyConfig {
@Value("${mybatis.mapperLocations}")private String mapperLocations;@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource druidDataSource() {
return new DruidDataSource();}@Beanpublic DataSourceProxy dataSourceProxy(DataSource druidDataSource){
return new DataSourceProxy(druidDataSource);}@Beanpublic SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSourceProxy);ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();bean.setMapperLocations(resolver.getResources(mapperLocations));return bean.getObject();}
}
⑥ 测试
经测试,上述过程能完成全局事务的回滚。若想完成对大型项目进行事务管理,可以尝试选用阿里云的全局事务服务GTS
。