分布式事务解决方案 Seata
官方文档:https://seata.io/zh-cn/docs/overview/what-is-seata.html
Seata Server 搭建
官方文档:https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html
涉及文件:https://github.com/seata/seata/tree/1.4.0/script
- client
存放client端sql脚本 (包含 undo_log表) ,参数配置
- config-center
各个配置中心参数导入脚本,config.txt(包含server和client,原名nacos-config.txt)为通用参数文件
- server
server端数据库脚本 (包含 lock_table、branch_table 与 global_table) 及各个容器配置
下载 Seata Server
地址:https://github.com/seata/seata/releases 根据版本下载
Seata 配置文件
查看静态资源中的
\script\config-center\config.txt
文件,根据官方文档按需修改
-
修改 server 端 数据存储方式 为 mysql 修改驱动类名、连接信息和用户名密码
store.db.dbType=mysql store.db.driverClassName=com.mysql.cj.jdbc.Driver store.db.url=jdbc:mysql://127.0.0.1:3306/seata_server?useUnicode=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true store.db.user=root store.db.password=root
Seata 事务分组
官方文档:https://seata.io/zh-cn/docs/user/txgroup/transaction-group.html
当一个事务组不可用时 可动态的切换到另一个事务组 保证 HA (高可用 )
使用方式
Server端配置
-
查看静态资源中的
\script\config-center\config.txt
文件 找到如下配置# service.vgroupMapping.{事务组名称}={事务组集群名称} service.vgroupMapping.my_test_tx_group=default # service.{事务组集群名称}.grouplist={SeataServer ip:port} service.default.grouplist=127.0.0.1:8091
-
将以上配置进行修改
事务组名称 & 集群名称可自定义
service.vgroupMapping.default_tx_group=default service.default.grouplist=127.0.0.1:8091
Client 端配置
-
指定所使用的事务组名称即可
这样 就可以通过配置中心的配置查找到事务组集群信息了
seata: tx-service-group: default_tx_group
Seata Server 整合 Nacos
整合注册中心
-
修改
\seata-server-1.4.2\conf\registry.conf
指定注册方式 注册中心地址 应用名称等
registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa type = "nacos" nacos { application = "seata-server" serverAddr = "192.168.59.102:8848" group = "SEATA_GROUP" namespace = "" cluster = "default" username = "" password = "" } }
整合配置中心
-
修改
\seata-server-1.4.2\conf\registry.conf
1.4.2 之前 指定配置存储方式 配置中心中心地址 分组 等 因为配置项较多 可以考虑使用单独的nacos 配置命名空间
1.4.2开始,支持了使用一个配置文件取获取所有配置 只需要将 config.txt 中的配置复制到nacos配置中心即可 例如:
seata.properties
config { # file、nacos 、apollo、zk、consul、etcd3 type = "nacos" nacos { serverAddr = "192.168.59.102:8848" namespace = "" group = "SEATA_GROUP" username = "" password = "" dataId = "seata.properties" } }
上传配置至Nacos配置中心
1.4.2 前的版本需要使用脚本上传配置 具体方法可到 https://seata.io/zh-cn/docs/user/configurations.html 查看
1.4.2开始在配置中心新建配置文件 并在配置中指定 dataId 即可
修改事务日志存放位置
如果 上面的配置存放位置为nacos则到nacos中修改
config.type= nacos
时
-
初始化数据库
查看静态资源中的
\script\server\db\
文件夹下的sql脚本,找到对应的sql脚本进行初始化mysql 脚本
-- -------------------------------- 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;
-
修改
\seata-server-1.4.2\conf\file.conf
只适用于
config.type= file
时
指定存储方式以及存储配置store { ## store mode: file、db、redis mode = "db" ## database store property db { ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc. datasource = "druid" ## mysql/oracle/postgresql/h2/oceanbase etc. dbType = "mysql" driverClassName = "com.mysql.jdbc.Driver" ## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param url = "jdbc:mysql://127.0.0.1:3306/seata_server?rewriteBatchedStatements=true" user = "root" password = "root" minConn = 5 maxConn = 100 globalTable = "global_table" branchTable = "branch_table" lockTable = "lock_table" queryLimit = 100 maxWait = 5000 } }
Seata AT模式的使用
官方文档:https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.html
AT 模式介绍 :https://seata.io/zh-cn/docs/dev/mode/at-mode.html
AT模式同样基于 二阶段提交 2PC 数据回滚机制依靠 undo_log 表
数据库中添加 undo_log 表
静态资源目录
/script/client/at/db/
脚本
-- 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`
(
`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(6) NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime',
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
添加配置
seata:
# 指定事务分组
tx-service-group: default_tx_group
# 指定SeataServer注册中心信息
registry:
type: nacos
nacos:
application: seata-server
group: SEATA_GROUP
server-addr: ${spring.cloud.nacos.config.server-addr}
# 指定SeataServer配置中心信息
config:
type: nacos
nacos:
group: SEATA_GROUP
server-addr: ${spring.cloud.nacos.config.server-addr}
# 指定seata配置文件data id
data-id: seata.properties
在事务发起方使用注解 @GlobalTransactional
其他事务分支使用 @Transactional 即可
-
例如:
/** * 点赞数据异步落库<br/> * 1.更新文章点赞数据(更新点赞数量) 远程调用 需要分布式事务<br/> * 2.更新评论点赞数据(更新点赞数量)<br/> * 3.更新回复点赞数据(更新点赞数量)<br/> * 4.更新点赞详情(点赞类型 数据等)<br/> */ @GlobalTransactional @XxlJob("saveArticleLikedCount") public void saveArticleLikedCount() { ..... }