1.模式简介与选择

1.1模式简介

Seata的应用-个人思路 - 图1

1.2模式选择

通过对各种模式的理解和部分模式尝试使用。我认为AT模式比较合适
理由:
①当前项目使用的是Mysql数据库,支持事务,符合AT模式的使用前提
②AT模式不需要手动编写提交或回滚代码,原代码不用做改动
③AT模式的学习资源和介绍丰富:
SpringCloudAlibaba提供的Seata使用示例是AT模式的
Seata官方快速启动也是针对AT模式,并且对AT模式的相关介绍高于其他各个模式
网上的博客较其他的模式要多

2.数据库的修改

2.1Seata数据库创建

2.1.1测试库和开发库

测试库和开发库都在 10.11.0.215的Mysql中因此,此Mysql上创建 test_seata和seata两个数据库,并且两个库分别创建3个相同的表
参考:https://github.com/seata/seata/blob/develop/script/server/db/mysql.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(96),
  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;

2.1.2生产库

生产库的话应该是创建一个 seata数据库即可,sql语句 同上。

2.2undo_log表的创建

在用到的数据库中创建undo_log表即可
参考:https://github.com/seata/seata/blob/develop/script/client/at/db/mysql.sql

  1. -- for AT mode you must to init this sql for you business database. the seata server not need it.
  2. CREATE TABLE IF NOT EXISTS `undo_log`
  3. (
  4. `branch_id` BIGINT(20) NOT NULL COMMENT 'branch transaction id',
  5. `xid` VARCHAR(100) NOT NULL COMMENT 'global transaction id',
  6. `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
  7. `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info',
  8. `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status',
  9. `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime',
  10. `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime',
  11. UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
  12. ) ENGINE = InnoDB
  13. AUTO_INCREMENT = 1
  14. DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';

3.Seata-Server的部署

3.1开发环境的Seata-Server的部署

1.开发环境的Seata-Server采用的方式与开发环境nacos的使用方式相同,开发人员启动自己的Seata-Server
2.Seata-Sever配置好打包到项目中即可
3.Seata-Server中的文件配置(register.conf)

  1. #注册在本地
  2. registry {
  3. # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  4. type = "nacos"
  5. nacos {
  6. application = "seata-server"
  7. serverAddr = "127.0.0.1:8848"
  8. group = "SEATA_GROUP"
  9. namespace = ""
  10. cluster = "default"
  11. username = "nacos"
  12. password = "nacos"
  13. }
  14. }
  15. #去220找配置
  16. config {
  17. # file、nacos 、apollo、zk、consul、etcd3
  18. type = "nacos"
  19. nacos {
  20. application = "seata-server"
  21. serverAddr = "10.11.0.220:8855"
  22. group = "SEATA_GROUP"
  23. namespace = "dev-seata空间的id"
  24. cluster = "default"
  25. username = "appconnect"
  26. password = "appconnect"
  27. }
  28. }

3.2测试环境的Seata-Sever部署

1.测试环境的Seata-Server采用的方式与测试环境nacos的使用方式也相同。
2.当前测试环境nacos也是重新启动一份的,所以seata-server在测试环境中也启动一份即可
3.配置文件(register.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 = ""
  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. application = "seata-server"
  19. serverAddr = "10.11.0.220:8855"
  20. group = "SEATA_GROUP"
  21. namespace = "test-seata空间的id"
  22. cluster = "default"
  23. username = "appconnect"
  24. password = "appconnect"
  25. }
  26. }

3.3生产环境的Seata-Sever部署

1.生产环境的Seata-Server采取高可用的配置方式;
2.具体操作:在不同的生产服务器上启动多个Seata-Server即可,数量不限
3.配置文件(register.conf)

  1. registry {
  2. # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  3. type = "nacos"
  4. nacos {
  5. application = "seata-server"
  6. serverAddr = "10.11.0.220:8855"
  7. group = "SEATA_GROUP"
  8. namespace = "生产服务注册空间id"
  9. cluster = "default"
  10. username = "appconnect"
  11. password = "appconnect"
  12. }
  13. }
  14. config {
  15. # file、nacos 、apollo、zk、consul、etcd3
  16. type = "nacos"
  17. nacos {
  18. application = "seata-server"
  19. serverAddr = "10.11.0.220:8855"
  20. group = "SEATA_GROUP"
  21. namespace = "pro-seata空间的id"
  22. cluster = "default"
  23. username = "appconnect"
  24. password = "appconnect"
  25. }
  26. }

4.Nacos关于Seata-Server的配置

4.1命名空间的创建

1.分别创建三个命名空间
①dev-seata:存放开发环境的seata配置
②test-seata:存放测试环境的seata配置
③pro-seata:存放生产环境的seata配置
image.png

4.2各个配置空间的配置初始化

参考:https://github.com/seata/seata/tree/develop/script/config-center
先准备好以下2个文件config.txt和nacos-config.sh
1.准备config.txt

  1. transport.type=TCP
  2. transport.server=NIO
  3. transport.heartbeat=true
  4. transport.enableClientBatchSendRequest=false
  5. transport.threadFactory.bossThreadPrefix=NettyBoss
  6. transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
  7. transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
  8. transport.threadFactory.shareBossWorker=false
  9. transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
  10. transport.threadFactory.clientSelectorThreadSize=1
  11. transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
  12. transport.threadFactory.bossThreadSize=1
  13. transport.threadFactory.workerThreadSize=default
  14. transport.shutdown.wait=3
  15. service.vgroupMapping.my_test_tx_group=default
  16. service.enableDegrade=false
  17. service.disableGlobalTransaction=false
  18. client.rm.asyncCommitBufferLimit=10000
  19. client.rm.lock.retryInterval=10
  20. client.rm.lock.retryTimes=30
  21. client.rm.lock.retryPolicyBranchRollbackOnConflict=true
  22. client.rm.reportRetryCount=5
  23. client.rm.tableMetaCheckEnable=false
  24. client.rm.sqlParserType=druid
  25. client.rm.reportSuccessEnable=false
  26. client.rm.sagaBranchRegisterEnable=false
  27. client.tm.commitRetryCount=5
  28. client.tm.rollbackRetryCount=5
  29. client.tm.defaultGlobalTransactionTimeout=60000
  30. client.tm.degradeCheck=false
  31. client.tm.degradeCheckAllowTimes=10
  32. client.tm.degradeCheckPeriod=2000
  33. store.mode=db
  34. store.db.datasource=druid
  35. store.db.dbType=mysql
  36. store.db.driverClassName=com.mysql.jdbc.Driver
  37. store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
  38. store.db.user=username
  39. store.db.password=password
  40. store.db.minConn=5
  41. store.db.maxConn=30
  42. store.db.globalTable=global_table
  43. store.db.branchTable=branch_table
  44. store.db.queryLimit=100
  45. store.db.lockTable=lock_table
  46. store.db.maxWait=5000
  47. server.recovery.committingRetryPeriod=1000
  48. server.recovery.asynCommittingRetryPeriod=1000
  49. server.recovery.rollbackingRetryPeriod=1000
  50. server.recovery.timeoutRetryPeriod=1000
  51. server.maxCommitRetryTimeout=-1
  52. server.maxRollbackRetryTimeout=-1
  53. server.rollbackRetryTimeoutUnlockEnable=false
  54. client.undo.dataValidation=true
  55. client.undo.logSerialization=jackson
  56. client.undo.onlyCareUpdateColumns=true
  57. server.undo.logSaveDays=7
  58. server.undo.logDeletePeriod=86400000
  59. client.undo.logTable=undo_log
  60. client.log.exceptionRate=100
  61. transport.serialization=seata
  62. transport.compressor=none
  63. metrics.enabled=false
  64. metrics.registryType=compact
  65. metrics.exporterList=prometheus
  66. metrics.exporterPrometheusPort=9898

2.准备nacos-config.sh

  1. #!/usr/bin/env bash
  2. # Copyright 1999-2019 Seata.io Group.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at、
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. while getopts ":h:p:g:t:u:w:" opt
  16. do
  17. case $opt in
  18. h)
  19. host=$OPTARG
  20. ;;
  21. p)
  22. port=$OPTARG
  23. ;;
  24. g)
  25. group=$OPTARG
  26. ;;
  27. t)
  28. tenant=$OPTARG
  29. ;;
  30. u)
  31. username=$OPTARG
  32. ;;
  33. w)
  34. password=$OPTARG
  35. ;;
  36. ?)
  37. echo " USAGE OPTION: $0 [-h host] [-p port] [-g group] [-t tenant] [-u username] [-w password] "
  38. exit 1
  39. ;;
  40. esac
  41. done
  42. if [[ -z ${host} ]]; then
  43. host=localhost
  44. fi
  45. if [[ -z ${port} ]]; then
  46. port=8848
  47. fi
  48. if [[ -z ${group} ]]; then
  49. group="SEATA_GROUP"
  50. fi
  51. if [[ -z ${tenant} ]]; then
  52. tenant=""
  53. fi
  54. if [[ -z ${username} ]]; then
  55. username=""
  56. fi
  57. if [[ -z ${password} ]]; then
  58. password=""
  59. fi
  60. nacosAddr=$host:$port
  61. contentType="content-type:application/json;charset=UTF-8"
  62. echo "set nacosAddr=$nacosAddr"
  63. echo "set group=$group"
  64. failCount=0
  65. tempLog=$(mktemp -u)
  66. function addConfig() {
  67. curl -X POST -H "${contentType}" "http://$nacosAddr/nacos/v1/cs/configs?dataId=$1&group=$group&content=$2&tenant=$tenant&username=$username&password=$password" >"${tempLog}" 2>/dev/null
  68. if [[ -z $(cat "${tempLog}") ]]; then
  69. echo " Please check the cluster status. "
  70. exit 1
  71. fi
  72. if [[ $(cat "${tempLog}") =~ "true" ]]; then
  73. echo "Set $1=$2 successfully "
  74. else
  75. echo "Set $1=$2 failure "
  76. (( failCount++ ))
  77. fi
  78. }
  79. count=0
  80. for line in $(cat "./config.txt" | sed s/[[:space:]]//g); do
  81. (( count++ ))
  82. key=${line%%=*}
  83. value=${line#*=}
  84. addConfig "${key}" "${value}"
  85. done
  86. echo "========================================================================="
  87. echo " Complete initialization parameters, total-count:$count , failure-count:$failCount "
  88. echo "========================================================================="
  89. if [[ ${failCount} -eq 0 ]]; then
  90. echo " Init nacos config finished, please start seata-server. "
  91. else
  92. echo " init nacos config fail. "
  93. fi

4.2.1开发环境pro-seata命名空间的seata配置信息初始化

1.将config.txt中数据库配置修改

  1. service.vgroupMapping.yurun_dev_tx_group=default
  2. store.db.url=jdbc:mysql://10.11.0.215:3306/seata?useUnicode=true

2.执行命令

  1. sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t (dev-seata命空间id) -u (nacos登录名) -w (nacos登录密码)
  2. 实例:
  3. sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t f2edbd24-10e8-4143-b01b-3b6a2c916d38 -u nacos -w nacos

4.2.2测试环境test-seata命名空间的seata配置信息初始化

1.将config.txt中的数据库配置修改

  1. service.vgroupMapping.yurun_test_tx_group=default
  2. store.db.url=jdbc:mysql://10.11.0.215:3306/test_seata?useUnicode=true

2.执行命令

  1. sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t (dev-seata命空间id) -u (nacos登录名) -w (nacos登录密码)
  2. 实例:
  3. sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 49e16ac0-1ff4-49e2-997e-6a3c236a536b -u nacos -w nacos

4.2.3生产环境pro-seata命名空间的seata配置信息初始化

1.将config.txt中的数据库配置修改

  1. service.vgroupMapping.yurun_pro_tx_group=default
  2. store.db.url=jdbc:mysql://生产库ip:3306/seata?useUnicode=true

2.执行命令

  1. sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t (dev-seata命空间id) -u (nacos登录名) -w (nacos登录密码)
  2. 实例:
  3. sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 4eacde77-104b-4ae5-82a7-8131f1a07740 -u nacos -w nacos

5.各个微服务的seata相关的配置

5.1pom文件

分布式事务的参与者需要引入seata

  1. <!--seata-->
  2. <dependency>
  3. <groupId>io.seata</groupId>
  4. <artifactId>seata-spring-boot-starter</artifactId>
  5. <version>1.3.0</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.alibaba.cloud</groupId>
  9. <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  10. <exclusions>
  11. <exclusion>
  12. <groupId>io.seata</groupId>
  13. <artifactId>seata-spring-boot-starter</artifactId>
  14. </exclusion>
  15. </exclusions>
  16. </dependency>

5.2开发环境关于seata的nacos配置文件(seata-client.yaml)

  1. seata:
  2. tx-service-group: yurun_dev_tx_group
  3. registry:
  4. type: nacos
  5. nacos:
  6. server-addr: localhost:8848
  7. username: nacos
  8. password: nacos
  9. config:
  10. type: nacos
  11. nacos:
  12. username: appconnect
  13. password: appconnect
  14. namespace: dev-seata命名空间id
  15. serverAddr: 10.11.0.220:8855

5.3测试环境关于seata的nacos配置文件(seata-client.yaml)

  1. seata:
  2. tx-service-group: yurun_test_tx_group
  3. registry:
  4. type: nacos
  5. nacos:
  6. server-addr: localhost:8848
  7. username: nacos
  8. password: nacos
  9. config:
  10. type: nacos
  11. nacos:
  12. username: appconnect
  13. password: appconnect
  14. namespace: test-seata命名空间id
  15. serverAddr: 10.11.0.220:8855

5.4生产环境关于seata的nacos配置文件(seata-client.yaml)

  1. seata:
  2. tx-service-group: yurun_pro_tx_group
  3. registry:
  4. type: nacos
  5. nacos:
  6. server-addr: 10.11.0.220:8855
  7. username: appconnect
  8. password: appconnect
  9. namespace: 生产的服务注册命名空间id
  10. config:
  11. type: nacos
  12. nacos:
  13. username: appconnect
  14. password: appconnect
  15. namespace: pro-seata命名空间id
  16. serverAddr: 10.11.0.220:8855

5.5总结

对于seata-client.yaml分别在10.11.0.220的nacos中不同命名空间放置即可,在每个需要分布式事务的bootstrap.yml中的nacos配置文件中添加即可:
image.png

6.使用

在需要分布式事务的方法上添加@GlobalTransactional
但是对于我们电商现在的中台,只有controller层,异常不给抛出,Controller方法加注解也没用,所以对代码改造是:
在中台添加一个Service层,在service层方法上添加注解即可实现分布式事务