Spring Cloud Alibaba Seata学习
Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成。
本文参考官网:https://seata.io
1 基础配置
使用nacos作为注册中心和配置中心
1.1 seata-server配置
版本1.4.2
1.1.1 修改register.conf
位置:{SEATA_HOME}/conf/register.conf
内容如下:
registry {
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
}
config {
type = "nacos"
nacos {
serverAddr = "127.0.0.1:8848"
namespace = ""
group = "SEATA_GROUP"
username = "nacos"
password = "nacos"
dataId = "seataServer.properties"
}
}
1.1.2 修改config.txt
下载config-conter中的config.txt和/nacos/nacos-config.sh
修改config.txt的内容
store.mode=db;
#数据库连接属性
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
store.db.user=username
store.db.password=password
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
Server端存储模式(store.mode)现有file、db、redis三种;
注: file模式为单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高;
db模式为高可用模式,全局事务会话信息通过db共享,相应性能差些;
redis模式Seata-Server 1.3及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置合适当前场景的redis持久化配置.
server | client |
---|---|
store.mode: file,db,redis | config.type: file、nacos 、apollo、zk、consul、etcd3、custom |
#only db: | #only file: |
store.db.driverClassName | service.default.grouplist |
store.db.url | #All: |
store.db.user | service.vgroupMapping.my_test_tx_group |
store.db.password | service.disableGlobalTransaction |
1.1.3 上传config.txt配置
将config.txt的内容上传到nacos配置中心:先启动nacos,然后执行nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-a71a-2e5e3340b3ca -u username -w password
注:-t表示命名空间
1.1.4 建表
全局事务会话信息由3块内容构成,全局事务–>分支事务–>全局锁,对应表global_table、branch_table、lock_table
从官网获取脚本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;
1.1.5 启动seata-server
./seata-server.sh -h 127.0.0.1 -p 8091 -m db -n 1 -e test
-h: 注册到注册中心的ip
-p: Server rpc 监听端口
-m: 全局事务会话信息存储模式,file、db、redis,优先读取启动参数 (Seata-Server 1.3及以上版本支持redis)
-n: Server node,多个Server时,需区分各自节点,用于生成不同区间的transactionId,以免冲突
-e: 多环境配置参考 http://seata.io/en-us/docs/ops/multi-configuration-isolation.html
1.2 seata-client配置
依赖:
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
yml:
seata:
registry:
nacos:
server-addr: localhost:8848, localhost:8849
application: seata-server #默认为seata-server
type: nacos
config:
nacos:
server-addr: localhost:8848, localhost:8849
group: SEATA_GROUP #默认为SEATA_GROUP
type: nacos
tx-service-group: consumer-service #事务分组名
相应的需要在配置中心配置
service.vgroupMapping.consumer-service=default
说明:server-client根据tx-service-group: consumer-service
从nacos配置中心读取service.vgroupMapping.consumer-service=default
,也就是seata服务在nacos的集群名称(nacos中可以同一个服务可以有多个虚拟集群),然后找到对应的服务实例。
创建undo_log表
-- 注意此处0.3.0+ 增加唯一索引 ux_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;
启动遇到的错误
Caused by: java.lang.NoClassDefFoundError: io/seata/spring/annotation/datasource/SeataAutoDataSourceProxyCreator
原因:使用的alibaba could的版本不支持seata
使用版本说明:https://github.com/alibaba/spring-cloud-alibaba/wiki/版本说明#组件版本关系
2 seata原理
GlobalTransactionalInterceptor(方法拦截器-解析@GlobalTransactional注解)–>TransactionalTemplate.execute(根据事务传播行为,开始事务、执行业务逻辑、提交事务)—>DefaultGlobalTransaction.begin(绑定xid)—>DefaultTransactionManager.begin(远程调用TC开启事务,并返回xid)
流程说明:TM向TC注册,RM向TC注册。TM向TC发起开启全局事务的请求,并获得xid,向调用链路传递xid。各个链路接口执行完成,提交本地事务之前,向TC注册分支并申请全局锁。获得锁后,提交本地事务,上报事务状态给TC,释放全局锁。TM向TC发起全局提交或回滚的请求,继而TC向RM发起分支提交或回滚的请求。
RM与TC的通信:
RM通过AbstractNettyRemotingClient的实现类RmNettyRemotingClient向TC注册,并注册一系列处理器(RmBranchCommitProcessor、RmBranchRollbackProcessor、RmUndoLogProcessor等),通过AbstractNettyRemotingClient中定义的ClientHandler(Net ty的ChannelInboundHandlerAdapter),接收TC的消息,并根据消息的code执行processor。
TM通过AbstractNettyRemotingClient的实现类TmNettyRemotingClient与TC通信。
详细参考:https://my.oschina.net/objcoding/blog/4367965