这里写自定义目录标题
SpringCloudAlibaba Seata1.2.0集成
1. 下载seata-server 1.2.0
https://github.com/seata/seata/releases
2. 创建数据库支持(seata-server,seata-client)
2.1 创建seata-server数据库支持
https://github.com/seata/seata/tree/1.2.0/script
以mysql数据库为例,创建数据库seata,执行建表sql
-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `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`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
`branch_id` BIGINT NOT NULL,
`xid` VARCHAR(128) NOT NULL,
`transaction_id` BIGINT,
`resource_group_id` VARCHAR(32),
`resource_id` VARCHAR(256),
`branch_type` VARCHAR(8),
`status` TINYINT,
`client_id` VARCHAR(64),
`application_data` VARCHAR(2000),
`gmt_create` DATETIME(6),
`gmt_modified` DATETIME(6),
PRIMARY KEY (`branch_id`),
KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
`row_key` VARCHAR(128) NOT NULL,
`xid` VARCHAR(96),
`transaction_id` BIGINT,
`branch_id` BIGINT NOT NULL,
`resource_id` VARCHAR(256),
`table_name` VARCHAR(32),
`pk` VARCHAR(36),
`gmt_create` DATETIME,
`gmt_modified` DATETIME,
PRIMARY KEY (`row_key`),
KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
2.2 创建seata-client数据库支持
在业务服务对应的数据库中执行seata-client需要的建表sql
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'increment id',
`branch_id` BIGINT(20) NOT NULL COMMENT 'branch transaction id',
`xid` VARCHAR(100) NOT NULL COMMENT 'global transaction id',
`context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
`rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info',
`log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status',
`log_created` DATETIME NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME NOT NULL COMMENT 'modify datetime',
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
3. 修改seata-server配置,file.conf、registry.conf
file.conf
## transaction log store, only used in seata-server
store {
## store mode: file、db
mode = "db"
## database store property
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
datasource = "druid"
## mysql/oracle/postgresql/h2/oceanbase etc.
dbType = "mysql"
driverClassName = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://127.0.0.1:3306/seata"
user = "root"
password = "root"
minConn = 5
maxConn = 30
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
}
registry.conf
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "localhost:8848"
namespace = "my-seata-namespace"
cluster = "default"
username = "nacos"
password = "nacos"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd3
type = "nacos"
nacos {
serverAddr = "localhost:8848"
namespace = "my-seata-namespace"
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
}
}
4. 启动nacos,导入seataServer配置
建议阅读https://github.com/seata/seata/tree/1.2.0/script/config-center README.md内容,把seata项目检出到本地。
启动nacos后,在nacos-config.sh目录下执行
sh nacos-config.sh -h ${nacos-ip} -p ${nacos-port} -t ${nacos-namespace-id}
执行结束可以到nacos配置列表看下配置导入情况
5. 启动seata
6. seata-client配置(业务服务端)
6.1 maven增加seata依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>1.2.0</version>
</dependency>
6.2 修改application.yml增加seata支持
spring:
alibaba:
seata:
tx-service-group: my_test_tx_group
6.3 复制seata-server配置文件file.conf、registry.conf到项目
6.4 配置数据源代理
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
@Primary
@Bean("dataSource")
public DataSourceProxy dataSource(DataSource druidDataSource){
return new DataSourceProxy(druidDataSource);
}
@EnableAutoDataSourceProxy
6.5 在分布式业务入口增加全局事务注解
@GlobalTransactional(rollbackFor = Exception.class)
备注:
1. @GlobalTransactional注解只需要加载分布式业务入口处,其他service接口无需配置。
2. 使用feign调用分布式服务,如果配置了fallback,后面服务抛出异常会直接执行fallback导致无法回滚(rollbackFor = Exception.class)。这时可以再fallback实现方法内手动调用seata全局回滚。如果有更优的解决方案可以告诉我下。
@Override
public BizResponse insertAge(Integer age) {
//feign调用接口fallback后需要手动调用全局事务回滚
try {
String xid = RootContext.getXID();
GlobalTransactionContext.reload(xid).rollback();
} catch (TransactionException e) {
e.printStackTrace();
}
return BizResponse.fail("客户端降级处理insertAge," + Thread.currentThread().getName());
}
测试源码 https://gitee.com/zhkwork/springCloudDemo