Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
TC (Transaction Coordinator) 事务协调者 :维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM (Transaction Manager) 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM (Resource Manager) 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
关系图:
UNDO_LOG表:
1. 必须在每个业务数据库中创建,用于保存回滚操作数据;
2. 当全局提交时,记录删除;
3. 当全局回滚时,将现有数据撤销。还原至操作前的状态(UNDO_LOG表中的某个字段记录了操作前的数据);
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 模式下,用户只需关注自己的业务SQL,用户的业务SQL 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。
这个模式需要模块为Java语言,并且数据库支持本地事务。一个典型的分布式事务过程:
操作步骤如下:
1)下载安装seata
阿里seata官网下载,直接解压到指定目录,先配置再启动,
seata-server中,/conf目录下,有两个配置文件,需要结合自己的情况来修改:
2)修改conf/file.conf
文件
① 将mode="file"
改为mode="db"
② db部分配置mysql相关信息
db {
DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = "druid"
dbType = "mysql"
//注意如果是mysql8版本,此处采用cj驱动,url后缀需要加serverTimezone=Asia/Shanghai
driverClassName = "com.mysql.cj.jdbc.Driver"
url = "jdbc:mysql://rm-bp17dq6iz79761b8fxo.mysql.rds.aliyuncs.com:3306/seata?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8"
//用户名和密码
user = "seata_test"
password = "- seata1234abcd!"
minConn = 5
maxConn = 30
globalTable = "global_table"
branchTable = "branch_table"
lockTable = "lock_table"
queryLimit = 100
maxWait = 5000
}
③ 数据库对应上述配置新建seata
的DB,并分配给指定的用户权限
④ 初始化table,注意此处一定要初始化,并且1.0之后的版本没有sql脚本,这里贴出来
-- 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`)
);
-- the table to store seata xid data
-- 0.7.0+ add context
-- you must to init this sql for you business databese. the seata server not need it.
-- 此脚本必须初始化在你当前的业务数据库中,用于AT 模式XID记录。与server端无关(注:业务数据库)
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
drop table `undo_log`;
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;
3)修改registry.conf
文件
这个文件内容分为registry
和config
2部分。
① 将registry和config部分的由type="file" 都换成type="nacos"(注意是2处地方)
② 将两处的nacos配置根据实际情况调整参数。
nacos {
application = "seata-server"
serverAddr = "nacos.it235.com:80"
group = "SEATA_GROUP"
namespace = "343f2aa2-1a42-43ea-b078-33ab7d58bd6a"
cluster = "default"
username = "nacos"
password = "nacos"
}
4)修改conf/logback.xml
的文件(可选操作)
将${user.home}
改为具体的seata
目录,如F:\hliedu\cloud\seata-server-1.3.0\seata
,那么配置如下:
5)双击启动bin/seata-server.bat
文件启动服务(有可能出现闪退)
6)为了方便查看更加清晰的日志,建议使用cmd
的方式启动
① 打开CMD窗口,使用cd命令切换到seata
的bin
目录
② 输入seata-server.bat
回车
7)启动成功的结果如下
1)导入相关依赖 spring-cloud-alibaba-seata
2)各数据库加入undo_log
表
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;
3)application.yaml配置
除了常规配置外,这里还要配置下事务组信息:
spring:
cloud:
alibaba:
seata:
# 这个fsp_tx_group自定义命名很重要,server,client都要保持一致
tx-service-group: fsp_tx_group
4)file.conf和registry.conf的配置
把seata-server中的这两个配置好的文件copy到resource目录下,做以下修改:
① file.conf
service {
#vgroup->rgroup
# 这个fsp_tx_group自定义命名很重要,server,client都要保持一致
vgroup_mapping.fsp_tx_group = "default"
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
disableGlobalTransaction = false
}
registry.conf主要是配置注册中心,看情况做修改
5)数据源代理
这个是要特别注意的地方,seata对数据源做了代理和接管,在每个参与分布式事务的服务中,都要做如下配置:
① 取消数据源自动创建
// 在启动类中取消数据源的自动创建
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) //这个注解里添加exclude属性
@MapperScan("com.fly.demo.dao")
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServerApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServerApplication.class, args);
}
}
② 自定义数据源配置
/**
* 数据源代理
* @author lrp
*/
@Configuration
public class DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
@Primary
@Bean("dataSource")
public DataSourceProxy dataSource(DataSource druidDataSource){
return new DataSourceProxy(druidDataSource);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSourceProxy dataSourceProxy)throws Exception{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSourceProxy);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath*:/mapper/*.xml"));
sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return sqlSessionFactoryBean.getObject();
}
}
1. 去掉每个服务的本地事务控制(一般是Service上加transitional注解)
2. 在TM的业务类的全局事务的方法上加上GlobalTransaction注解
有四个微服务模块:虚拟机模块、镜像模块、模板模块和网络模块。其中虚拟机的创建需要镜像、模块和网络。虚拟机的创建需要调用其他三个模块,此时创建虚拟机为一个全局事务(TM),其他三个模块都是资源(RM)。多个全局事务都被事务协调器(TC)管理。
如上所述,任意一个RM报错,其他的RM仍能执行成功,此时undo_log表会记录更改前后的信息,seata-server会自动将这个TM回滚到更改前的状态。
1) 内存不足(一般出现较少),在seata-server.bat/seata-serve.sh的文件中配置运行内存大小
2)没有logs文件夹,手动添加
3)JRE的问题,当(1)和(2)都没问题时在考虑这一点。需要重装jdk,重装时,所有选项都要勾选。