当前位置:   article > 正文

一文搞懂微服务的Seata➕Nacos配置_seata nacos配置

seata nacos配置

前言

在分布式系统中,事务管理是一个非常重要的问题。Seata是一款轻量级的分布式事务解决方案,它基于阿里巴巴的Dubbo RPC框架,并且可以与Spring Cloud集成。本文将介绍如何在Spring Cloud Alibaba中使用Seata,包括Seata的架构、配置以及使用方法。

准备工作

在开始配置Spring Cloud Alibaba Seata之前,我们需要先确保系统已满足以下条件:

  • Java运行环境已安装
  • Maven已安装
  • 了解Spring Boot基础知识

Seata架构

Seata的架构包括三个组件:Transaction Coordinator(TC)、Transaction Manager(TM)和Resource Manager(RM)。其中,TC负责全局事务的协调和管理,TM负责本地事务的管理,RM负责资源的分支事务管理。

下图展示了Seata的基本架构:

image-20230804151220476

在Seata中,全局事务由一个TC实例进行协调和管理。TC可以通过与TM和RM进行通信来实现全局事务的提交和回滚。

在一个分布式系统中,每个服务都可以作为一个TM实例运行。当服务需要进行事务操作时,TM会向TC注册一个本地事务,并且向RM发送分支事务请求。RM可以将分支事务与本地事务进行关联,从而实现分支事务的管理。

Seata融合Nacos

Seata远端配置

Seata是一款开源的分布式事务解决方案,而Nacos是一款分布式配置中心。要将Seata与Nacos进行融合,可以按照以下步骤操作:

从Seata官网仓库下载源码包,并解压,建表。

Seata Server 共有以下 3 种存储模式(store.mode):

模式说明准备工作
file文件存储模式,默认存储模式; 该模式为单机模式,全局事务的会话信息在内存中读写,并持久化本地文件 root.data,性能较高-
db数据库存储模式; 该模式为高可用模式,全局事务会话信息通过数据库共享,性能较低。建数据库表
redis缓存处处模式; Seata Server 1.3 及以上版本支持该模式,性能较高,但存在事务信息丢失风险,配置 redis 持久化配置

在 db 模式下,我们需要针对全局事务的会话信息创建以下 3 张数据库表。

  • 全局事务表,对应的表为:global_table
  • 分支事务表,对应的表为:branch_table
  • 全局锁表,对应的表为:lock_table

在 MySQL 中,创建一个名为 seata 的数据库实例,并在该数据库内执行以下 SQL。

global_table 的建表 SQL 如下。

  1. less复制代码-- -------------------------------- storeMode为“db”时使用的脚本 --------------------------------
  2. -- 全局事务表--
  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;

branch_table 的建表 SQL 如下。

  1. less复制代码-- 事务分支表 --
  2. CREATE TABLE IF NOT EXISTS `branch_table`
  3. (
  4. `branch_id` BIGINT NOT NULL,
  5. `xid` VARCHAR(128) NOT NULL,
  6. `transaction_id` BIGINT,
  7. `resource_group_id` VARCHAR(32),
  8. `resource_id` VARCHAR(256),
  9. `branch_type` VARCHAR(8),
  10. `status` TINYINT,
  11. `client_id` VARCHAR(64),
  12. `application_data` VARCHAR(2000),
  13. `gmt_create` DATETIME(6),
  14. `gmt_modified` DATETIME(6),
  15. PRIMARY KEY (`branch_id`),
  16. KEY `idx_xid` (`xid`)
  17. ) ENGINE = InnoDB
  18. DEFAULT CHARSET = utf8;

lock_table 的建表 SQL 如下。

  1. less复制代码-- 锁定表--
  2. CREATE TABLE IF NOT EXISTS `lock_table`
  3. (
  4. `row_key` VARCHAR(128) NOT NULL,
  5. `xid` VARCHAR(96),
  6. `transaction_id` BIGINT,
  7. `branch_id` BIGINT NOT NULL,
  8. `resource_id` VARCHAR(256),
  9. `table_name` VARCHAR(32),
  10. `pk` VARCHAR(36),
  11. `gmt_create` DATETIME,
  12. `gmt_modified` DATETIME,
  13. PRIMARY KEY (`row_key`),
  14. KEY `idx_branch_id` (`branch_id`)
  15. ) ENGINE = InnoDB
  16. DEFAULT CHARSET = utf8;

distributed_lock 的建表 SQL 如下。

  1. sql复制代码-- seata新版本加的锁表--
  2. CREATE TABLE IF NOT EXISTS `distributed_lock`
  3. (
  4. `lock_key` CHAR(20) NOT NULL,
  5. `lock_value` VARCHAR(20) NOT NULL,
  6. `expire` BIGINT,
  7. PRIMARY KEY (`lock_key`)
  8. ) ENGINE = INNODB
  9. DEFAULT CHARSET = utf8mb4;
  10. INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
  11. INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
  12. INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
  13. INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);

数据库中添加回滚日志表UNDO_LOG:

UNDO_LOG必须在每个业务数据库中出现,用于保存回滚操作数据。

  • 当全局事务提交时,对应的UNDO_LOG记录直接删除。
  • 当全局事务回滚时,通过该表回滚到以前的数据,并删除UNDO_LOG记录。

Seata的UNDO_LOG表和数据库的UNDO_LOG是相似的,只不过它们的范围不一样

undo_log 的建表 SQL 如下。

  1. r复制代码CREATE TABLE `undo_log` (
  2. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3. `branch_id` bigint(20) NOT NULL,
  4. `xid` varchar(100) NOT NULL,
  5. `context` varchar(128) NOT NULL,
  6. `rollback_info` longblob NOT NULL,
  7. `log_status` int(11) NOT NULL,
  8. `log_created` datetime NOT NULL,
  9. `log_modified` datetime NOT NULL,
  10. PRIMARY KEY (`id`),
  11. UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
  12. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

注意:

  • 前面的UNDO_LOG表是加在业务数据库中的。每个业务数据库都要有UNDO_LOG
  • seata1.4.2之后,需要回滚的表日期类型不能使用datetime,可以使用timestamp

在Seata的script/config-center路径下获取config.txt文件。

  1. ini复制代码#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
  2. #Transport configuration, for client and server
  3. transport.type=TCP
  4. transport.server=NIO
  5. transport.heartbeat=true
  6. transport.enableTmClientBatchSendRequest=false
  7. transport.enableRmClientBatchSendRequest=true
  8. transport.enableTcServerBatchSendResponse=false
  9. transport.rpcRmRequestTimeout=30000
  10. transport.rpcTmRequestTimeout=30000
  11. transport.rpcTcRequestTimeout=30000
  12. transport.threadFactory.bossThreadPrefix=NettyBoss
  13. transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
  14. transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
  15. transport.threadFactory.shareBossWorker=false
  16. transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
  17. transport.threadFactory.clientSelectorThreadSize=1
  18. transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
  19. transport.threadFactory.bossThreadSize=1
  20. transport.threadFactory.workerThreadSize=default
  21. transport.shutdown.wait=3
  22. transport.serialization=seata
  23. transport.compressor=none
  24. #Transaction routing rules configuration, only for the client
  25. service.vgroupMapping.default_tx_group=default
  26. #If you use a registry, you can ignore it
  27. service.default.grouplist=127.0.0.1:8091
  28. service.enableDegrade=false
  29. service.disableGlobalTransaction=false
  30. #Transaction rule configuration, only for the client
  31. client.rm.asyncCommitBufferLimit=10000
  32. client.rm.lock.retryInterval=10
  33. client.rm.lock.retryTimes=30
  34. client.rm.lock.retryPolicyBranchRollbackOnConflict=true
  35. client.rm.reportRetryCount=5
  36. client.rm.tableMetaCheckEnable=true
  37. client.rm.tableMetaCheckerInterval=60000
  38. client.rm.sqlParserType=druid
  39. client.rm.reportSuccessEnable=false
  40. client.rm.sagaBranchRegisterEnable=false
  41. client.rm.sagaJsonParser=fastjson
  42. client.rm.tccActionInterceptorOrder=-2147482648
  43. client.tm.commitRetryCount=5
  44. client.tm.rollbackRetryCount=5
  45. client.tm.defaultGlobalTransactionTimeout=60000
  46. client.tm.degradeCheck=false
  47. client.tm.degradeCheckAllowTimes=10
  48. client.tm.degradeCheckPeriod=2000
  49. client.tm.interceptorOrder=-2147482648
  50. client.undo.dataValidation=true
  51. client.undo.logSerialization=jackson
  52. client.undo.onlyCareUpdateColumns=true
  53. server.undo.logSaveDays=7
  54. server.undo.logDeletePeriod=86400000
  55. client.undo.logTable=undo_log
  56. client.undo.compress.enable=true
  57. client.undo.compress.type=zip
  58. client.undo.compress.threshold=64k
  59. #For TCC transaction mode
  60. tcc.fence.logTableName=tcc_fence_log
  61. tcc.fence.cleanPeriod=1h
  62. #Log rule configuration, for client and server
  63. log.exceptionRate=100
  64. #Transaction storage configuration, only for the server. The file, db, and redis configuration values are optional.
  65. store.mode=file
  66. store.lock.mode=file
  67. store.session.mode=file
  68. #Used for password encryption
  69. store.publicKey=
  70. #If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
  71. store.file.dir=file_store/data
  72. store.file.maxBranchSessionSize=16384
  73. store.file.maxGlobalSessionSize=512
  74. store.file.fileWriteBufferCacheSize=16384
  75. store.file.flushDiskMode=async
  76. store.file.sessionReloadReadSize=100
  77. #These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
  78. store.db.datasource=druid
  79. store.db.dbType=mysql
  80. store.db.driverClassName=com.mysql.jdbc.Driver
  81. store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true
  82. store.db.user=username
  83. store.db.password=password
  84. store.db.minConn=5
  85. store.db.maxConn=30
  86. store.db.globalTable=global_table
  87. store.db.branchTable=branch_table
  88. store.db.distributedLockTable=distributed_lock
  89. store.db.queryLimit=100
  90. store.db.lockTable=lock_table
  91. store.db.maxWait=5000
  92. #These configurations are required if the `store mode` is `redis`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `redis`, you can remove the configuration block.
  93. store.redis.mode=single
  94. store.redis.single.host=127.0.0.1
  95. store.redis.single.port=6379
  96. store.redis.sentinel.masterName=
  97. store.redis.sentinel.sentinelHosts=
  98. store.redis.maxConn=10
  99. store.redis.minConn=1
  100. store.redis.maxTotal=100
  101. store.redis.database=0
  102. store.redis.password=
  103. store.redis.queryLimit=100
  104. #Transaction rule configuration, only for the server
  105. server.recovery.committingRetryPeriod=1000
  106. server.recovery.asynCommittingRetryPeriod=1000
  107. server.recovery.rollbackingRetryPeriod=1000
  108. server.recovery.timeoutRetryPeriod=1000
  109. server.maxCommitRetryTimeout=-1
  110. server.maxRollbackRetryTimeout=-1
  111. server.rollbackRetryTimeoutUnlockEnable=false
  112. server.distributedLockExpireTime=10000
  113. server.xaerNotaRetryTimeout=60000
  114. server.session.branchAsyncQueueSize=5000
  115. server.session.enableBranchAsyncRemove=false
  116. server.enableParallelRequestHandle=false
  117. #Metrics configuration, only for the server
  118. metrics.enabled=false
  119. metrics.registryType=compact
  120. metrics.exporterList=prometheus
  121. metrics.exporterPrometheusPort=9898

在Nacos配置中心里新建seataServer.properties配置,并将config.txt文件内的内容复制进去。

image-20230804154027821

修改Seata服务的配置,具体包括:

  • 获取Seata的程序包并解压。

  • 进入conf目录下的registry.conf文件。

  • 找到registry下的type配置,将其改为nacos

  • 找到nacos配置并进行修改。

    config { type = "nacos" ​ nacos {   serverAddr = "127.0.0.1:8848"   group = "SEATA_GROUP"   namespace = ""   username = "nacos"   password = "nacos" } } ​ registry { type = "nacos" ​ nacos {   application = "seata-server"   serverAddr = "127.0.0.1:8848"   group = "SEATA_GROUP"   namespace = ""   cluster = "default"   username = "nacos"   password = "nacos" } }

编辑Nacos的配置,具体包括:

  • 在Nacos配置中心里新建seataServer.properties配置。
  • 将Seata的配置信息复制进去,如defaultregistry.conf中的default

启动Seata和Nacos服务,完成Seata与Nacos的融合。

image-20230804154332525

以上步骤详细描述了将Seata与Nacos进行融合的过程。请根据实际需求进行相应的调整和修改。

Seata本地配置

在项目中添加如下依赖:

  1. xml复制代码<dependency>
  2. <groupId>io.seata</groupId>
  3. <artifactId>seata-all</artifactId>
  4. <version>1.7.0</version>
  5. </dependency>
  1. 配置文件

在项目的配置文件中 application.yml 添加如下配置:

  1. yaml复制代码seata:
  2. enabled: true
  3. application-id: ${spring.application.name}
  4. tx-service-group: ${spring.application.name}-fescar-service-group
  5. service:
  6. vgroup-mapping:
  7. ${spring.application.name}-fescar-service-group: default
  8. group-default:
  9. default:
  10. defaultGlobalTransactionTimeout: 60000
  11. registry:
  12. type: nacos
  13. nacos:
  14. server-addr: ${spring.cloud.nacos.discovery.server-addr}
  15. namespace: ${spring.cloud.nacos.config.namespace}
  16. group: SEATA_GROUP
  17. cluster: default
  18. config:
  19. type: nacos
  20. nacos:
  21. server-addr: ${spring.cloud.nacos.discovery.server-addr}
  22. namespace: ${spring.cloud.nacos.config.namespace}
  23. group: SEATA_GROUP
  24. cluster: default

  • seata.enabled:是否启用Seata。
  • seata.application-id:Seata应用ID,通常使用Spring应用程序名称。
  • seata.tx-service-group:Seata事务服务组ID,通常使用${spring.application.name}-fescar-service-group
  • seata.service.vgroup-mapping:Seata服务分组映射。
  • seata.service.group-default:Seata服务默认配置。
  • seata.registry.type:Seata注册中心类型,这里使用的是Nacos。
  • seata.registry.nacos.server-addr:Nacos注册中心地址,从Spring Cloud配置中心获取。
  • seata.registry.nacos.namespace:Nacos注册中心命名空间,从Spring Cloud配置中心获取。
  • seata.registry.nacos.group:Nacos注册中心分组。
  • seata.registry.nacos.cluster:Nacos注册中心集群。
  • seata.config.type:Seata配置中心类型,这里使用的是Nacos。
  • seata.config.nacos.server-addr:Nacos配置中心地址,从Spring Cloud配置中心获取。
  • seata.config.nacos.namespace:Nacos配置中心命名空间,从Spring Cloud配置中心获取。
  • seata.config.nacos.group:Nacos配置中心分组。
  • seata.config.nacos.cluster:Nacos配置中心集群。

Seata使用方法

在Spring Cloud Alibaba中使用Seata非常简单,只需要按照如下步骤进行操作:

  1. 启动Seata Server

首先需要启动Seata Server,Seata Server是一个独立的进程,用于管理全局事务。可以通过下载Seata Server并运行启动脚本来启动Seata Server。

image-20230804153202315

  1. 配置数据源代理

在使用Seata时,需要使用数据源代理来拦截SQL语句,从而实现分支事务的管理。在Spring Cloud Alibaba中,可以使用Seata提供的数据源代理来实现。

具体来说,可以在项目中引入Seata提供的数据源代理依赖,并在数据源配置中使用Seata提供的数据源代理类来代理数据源。

例如,在使用Druid作为数据源时,可以按照如下方式配置数据源代理:

  1. xml复制代码<dependency>
  2. <groupId>io.seata</groupId>
  3. <artifactId>seata-datasource-proxy</artifactId>
  4. <version>1.7.0</version>
  5. </dependency>
  1. yaml复制代码spring:
  2. datasource:
  3. url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
  4. username: root
  5. password: 123456
  6. driver-class-name: com.mysql.cj.jdbc.Driver
  7. type: com.alibaba.druid.pool.DruidDataSource
  8. proxy-filters: com.alibaba.druid.filter.stat.StatFilter, io.seata.rm.datasource.SeataDataSourceProxy

在数据源配置中,将Seata提供的数据源代理类io.seata.rm.datasource.SeataDataSourceProxy添加到proxy-filters中即可。

  1. 配置分布式事务

主启动上加注解 @EnableTransactionManagement

在进行分布式事务操作时,需要通过Seata提供的@GlobalTransactional注解来标记全局事务。

例如,在使用MyBatis进行数据库操作时,可以按照如下方式使用@GlobalTransactional注解:

  1. less复制代码@Service
  2. public class UserServiceImpl implements UserService {
  3. @Autowired
  4. private UserMapper userMapper;
  5. @Override
  6. @GlobalTransactional
  7. public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
  8. User fromUser = userMapper.selectByAccount(fromAccount);
  9. User toUser = userMapper.selectByAccount(toAccount);
  10. fromUser.setBalance(fromUser.getBalance().subtract(amount));
  11. toUser.setBalance(toUser.getBalance().add(amount));
  12. userMapper.updateByPrimaryKey(fromUser);
  13. userMapper.updateByPrimaryKey(toUser);
  14. }
  15. }

在上述代码中,使用@GlobalTransactional注解标记了transfer()方法,从而实现了分布式事务。

故障排除

如果在配置或使用过程中遇到了问题,可以检查以下几点:

  • Seata相关配置是否正确
  • Seata Server是否正常启动,并可以被访问
  • Seata Client是否正确配置,并与Seata Server保持连接
  • 业务代码中是否正确使用了Seata的事务处理机制

通过仔细检查这些关键点,你应该能够顺利地配置和使用Spring Cloud Alibaba Seata,实现高效的数据存储和处理。

小结

本文介绍了在Spring Cloud Alibaba中使用Seata的方法,包括Seata的架构、配置以及使用方法。通过使用Seata,可以在分布式系统中实现分布式事务的管理,从而保证数据的一致性和完整性。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/813824
推荐阅读
相关标签
  

闽ICP备14008679号