Seata1分布式事务,安装、数据准备

1.Seata术语

是什么
Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。
官网:http://seata.io/zh-cn/
能干嘛
一个典型的分布式事务过程
分布式事务处理过程的一ID+三组件模型:

  • Transaction ID XID 全局唯一的事务ID
  • 三组件概念
  • TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
  • TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
  • RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

处理过程:

  1. TM向TC申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的XID;
  2. XID在微服务调用链路的上下文中传播;
  3. RM向TC注册分支事务,将其纳入XID对应全局事务的管辖;
  4. TM向TC发起针对XID的全局提交或回滚决议;
  5. TC调度XID下管辖的全部分支事务完成提交或回滚请求。

2.Seata-Server安装(https://www.jianshu.com/p/fda8f616ba22)

去哪下
发布说明: Releases · seata/seata (github.com)
怎么玩
本地Transactional
全局GlobalTransactional
SEATA 的分布式交易解决方案

我们只需要使用一个 @GlobalTransactional 注解在业务方法上:
Seata-Server安装 ( (25条消息) seata1.4.2环境搭建_u012586389的博客-CSDN博客_seata1.4.2 )

基于windows 单机版

注册中心:Nacos
配置中心:Nacos

  • seata 服务端配置修改
    conf 目录下 修改registry.conf文件
    注册类型改为nacos,及nacos的相关配置。最好新建一个命名空间专门隔离seata的服务和配置

registry.conf需要修改的部分 :

  1. registry {
  2. # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  3. type = "nacos"
  4. nacos {
  5. application = "seata-server"
  6. serverAddr = "127.0.0.1:8848"
  7. group = "SEATA_GROUP"
  8. namespace = "ce9eb940-4ef2-4e35-8451-2a755b6e196e"
  9. cluster = "default"
  10. username = "nacos"
  11. password = "nacos"
  12. }
  13. }
  14. config {
  15. # file、nacos 、apollo、zk、consul、etcd3
  16. type = "nacos"
  17. nacos {
  18. serverAddr = "127.0.0.1:8848"
  19. namespace = "ce9eb940-4ef2-4e35-8451-2a755b6e196e"
  20. group = "SEATA_GROUP"
  21. username = "nacos"
  22. password = "nacos"
  23. dataId = "seataServer.properties"
  24. }
  25. }

file.conf 需要修改的部分 :

  1. ## transaction log store, only used in seata-server
  2. store {
  3. ## store mode: file、db、redis
  4. mode = "db"
  5. ## rsa decryption public key
  6. publicKey = ""
  7. ## database store property
  8. db {
  9. ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
  10. datasource = "druid"
  11. ## datasource = "dbcp"
  12. ## mysql/oracle/postgresql/h2/oceanbase etc.
  13. dbType = "mysql"
  14. ## mysql 5.xx
  15. ## driverClassName = "com.mysql.jdbc.Driver"
  16. ## mysql 8.0
  17. driverClassName = "com.mysql.cj.jdbc.Driver"
  18. ## if using mysql to store the data, recommend add rewriteBatchedStatements=true in jdbc connection param
  19. ## url = "jdbc:mysql://127.0.0.1:3306/my-seata?rewriteBatchedStatements=true"
  20. url = "jdbc:mysql://127.0.0.1:3306/my-seata?useUnicode=true&characterEncoding=utf-8&useSSL=false&nullCatalogMeansCurrent=true&serverTimezone=Asia/Shanghai"
  21. user = "root"
  22. password = "root"
  23. minConn = 5
  24. maxConn = 100
  25. globalTable = "global_table"
  26. branchTable = "branch_table"
  27. lockTable = "lock_table"
  28. queryLimit = 100
  29. maxWait = 5000
  30. }
  31. }

需要注意mysql8的 driverClassName 和5.x版本写法略有区别
新建库seata,建表sql:

  1. -- -------------------------------- The script used when storeMode is 'db' --------------------------------
  2. -- the table to store GlobalSession data
  3. CREATE TABLE IF NOT EXISTS `global_table`
  4. (
  5. `xid` VARCHAR(128) NOT NULL,
  6. `transaction_id` BIGINT,
  7. `status` TINYINT NOT NULL,
  8. `application_id` VARCHAR(32),
  9. `transaction_service_group` VARCHAR(32),
  10. `transaction_name` VARCHAR(128),
  11. `timeout` INT,
  12. `begin_time` BIGINT,
  13. `application_data` VARCHAR(2000),
  14. `gmt_create` DATETIME,
  15. `gmt_modified` DATETIME,
  16. PRIMARY KEY (`xid`),
  17. KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
  18. KEY `idx_transaction_id` (`transaction_id`)
  19. ) ENGINE = InnoDB
  20. DEFAULT CHARSET = utf8;
  21. -- the table to store BranchSession data
  22. CREATE TABLE IF NOT EXISTS `branch_table`
  23. (
  24. `branch_id` BIGINT NOT NULL,
  25. `xid` VARCHAR(128) NOT NULL,
  26. `transaction_id` BIGINT,
  27. `resource_group_id` VARCHAR(32),
  28. `resource_id` VARCHAR(256),
  29. `branch_type` VARCHAR(8),
  30. `status` TINYINT,
  31. `client_id` VARCHAR(64),
  32. `application_data` VARCHAR(2000),
  33. `gmt_create` DATETIME(6),
  34. `gmt_modified` DATETIME(6),
  35. PRIMARY KEY (`branch_id`),
  36. KEY `idx_xid` (`xid`)
  37. ) ENGINE = InnoDB
  38. DEFAULT CHARSET = utf8;
  39. -- the table to store lock data
  40. CREATE TABLE IF NOT EXISTS `lock_table`
  41. (
  42. `row_key` VARCHAR(128) NOT NULL,
  43. `xid` VARCHAR(128),
  44. `transaction_id` BIGINT,
  45. `branch_id` BIGINT NOT NULL,
  46. `resource_id` VARCHAR(256),
  47. `table_name` VARCHAR(32),
  48. `pk` VARCHAR(36),
  49. `gmt_create` DATETIME,
  50. `gmt_modified` DATETIME,
  51. PRIMARY KEY (`row_key`),
  52. KEY `idx_branch_id` (`branch_id`)
  53. ) ENGINE = InnoDB
  54. DEFAULT CHARSET = utf8;

先启动Nacos端口号8848 nacos\bin\startup.cmd
再启动E:\myServices\seata-server-1.4.2\seata\seata-server-1.4.2\bin\seata-server.bat
下载源码:E:\myServices\seata-1.4.2 Releases · seata/seata (github.com)
config.txt配置放在安装seata-server的目录下,与bin目录同级

nacos-config.shcopy下来的文件放在安装seata目录下的conf目录

修改config.txt中的部分配置

将seata的配置导入到nacos的配置中心

conf目录下,使用git将seata的配置导入nacos配置中心,前提是电脑环境上安装了git

使用如下命令进行导入:

  1. sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 0af6e97b-a684-4647-b696-7c6d42aecce7 -u nacos -w nacos

参数详情:命令解析:-h -p 指定nacos的端口地址;-g 指定配置的分组,注意,是配置的分组;-t 指定命名空间id; -u -w指定nacos的用户名和密码,同样,这里开启了nacos注册和配置认证的才需要指定。
按回车等待配置导入成功.

出现如图信息,说明导入成功。也可用去Nacos配置中心查看

3.Seata业务数据库准备

以下演示都需要先启动Nacos后启动Seata,保证两个都OK。
分布式事务业务说明
这里我们会创建三个服务,一个订单服务,一个库存服务,一个账户服务。
当用户下单时,会在订单服务中创建一个订单, 然后通过远程调用库存服务来扣减下单商品的库存,再通过远程调用账户服务来扣减用户账户里面的余额,最后在订单服务中修改订单状态为已完成。
该操作跨越三个数据库,有两次远程调用,很明显会有分布式事务问题。
一言蔽之,下订单—>扣库存—>减账户(余额)。
创建业务数据库

  • seata_ order:存储订单的数据库;
  • seata_ storage:存储库存的数据库;
  • seata_ account:存储账户信息的数据库。

建库SQL

  1. CREATE DATABASE seata_order;
  2. CREATE DATABASE seata_storage;
  3. CREATE DATABASE seata_account;

按照上述3库分别建对应业务表

  • seata_order库下建t_order表 `` CREATE TABLE t_order (idBIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,user_idBIGINT(11) DEFAULT NULL COMMENT '用户id',product_idBIGINT(11) DEFAULT NULL COMMENT '产品id',countINT(11) DEFAULT NULL COMMENT '数量',moneyDECIMAL(11,0) DEFAULT NULL COMMENT '金额',status` INT(1) DEFAULT NULL COMMENT ‘订单状态: 0:创建中; 1:已完结’ ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

SELECT * FROM t_order;

  1. - seata_storage库下建t_storage

CREATE TABLE t_storage ( id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, product_id BIGINT(11) DEFAULT NULL COMMENT ‘产品id’, total INT(11) DEFAULT NULL COMMENT ‘总库存’, used INT(11) DEFAULT NULL COMMENT ‘已用库存’, residue INT(11) DEFAULT NULL COMMENT ‘剩余库存’ ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO seata_storage.t_storage(id, product_id, total, used, residue) VALUES (‘1’, ‘1’, ‘100’, ‘0’,’100’);

SELECT * FROM t_storage;

  1. - seata_account库下建t_account

CREATE TABLE t_account( id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT ‘id’, user_id BIGINT(11) DEFAULT NULL COMMENT ‘用户id’, total DECIMAL(10,0) DEFAULT NULL COMMENT ‘总额度’, used DECIMAL(10,0) DEFAULT NULL COMMENT ‘已用余额’, residue DECIMAL(10,0) DEFAULT ‘0’ COMMENT ‘剩余可用额度’ ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO seata_account.t_account(id, user_id, total, used, residue) VALUES (‘1’, ‘1’, ‘1000’, ‘0’, ‘1000’);

SELECT * FROM t_account;

  1. 按照上述3库分别建对应的回滚日志表
  2. - 订单-库存-账户3个库下**都需要建各自的回滚日志表**
  3. - \seata-server-0.9.0\seata\conf目录下的db_ undo_ log.sql
  4. - 建表SQL

— 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;

```