概述
文章目录
- 版本说明
- Seata术语
- 配置Seata服务端(TC)
- 配置Seata服务端(TC)数据源
- Docker安装Seata服务端(TC)
- 配置Seata客户端(TM和RM)
- 注意事项
- 其它知识
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。
版本说明
- Seata 1.5.1 (1.4.2版本会有时间序列化问题,网上有一些解决方案,试了但是没能解决,建议直接用1.5.0+版本)
- nacos 1.4.3
- SpringBoot 2.6.3
- java 1.8
- mysql 8.0+
Seata术语
Seata分TC、TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成。
- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
配置Seata服务端(TC)
配置Seata服务端(TC)数据源
- 数据库脚本 (包含 lock_table、branch_table 与 global_tabledian 、distributed_lock) ,注意:
distributed_lock
表是1.5.0+版本新加的。 - 数据库建表语句:https://github.com/seata/seata/tree/1.5.0/script/server/db
- 使用sql建表脚本创建服务端数据源,下面的服务端的
application.yml
配置文件中需要配置数据源的数据库相关信息。
Docker安装Seata服务端(TC)
- 拉取指定版本的seata-server镜像并运行
docker run --name seata-server -p 8091:8091 -p 7091:7091 seataio/seata-server:1.5.1
- 将resources目录文件拷出的临时容器
# docker cp seata-serve:/seata-server/resources /User/seata/config
docker cp seata-serve:/seata-server/resources [服务器本地存放配置文件地址]
-
拷出后,修改
application.yml
,然后有以下两种解决方案:- A:可以选择修改
application.yml
再docker cp [服务器本地存放配置文件地址] seata-serve:/seata-server/resources
进容器,然后重器Seata容器docker restart [容器名/容器ID]
- B: 可以删除
docker rm 容器名/容器ID
刚刚创建的容器,重新创建,并做好映射路径设置。
docker run --name seata-server -p 8091:8091 -p 7091:7091 -v [服务器本地存放配置文件地址]:/seata-server/resources seataio/seata-server
- A:可以选择修改
-
Seata 注册中心和配置中心配置支持 file,nacos, consul, apollo, zk, etcd3 等,可以参考从容器拷贝下来的
application.example.yml
官方yaml配置文档,下面是配置nacos的application.yml参考:
server:
port: 7091
spring:
application:
name: seata-server
logging:
config: classpath:logback-spring.xml
file:
path: ${user.home}/logs/seata
console:
user:
username: seata
password: seata
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
# 配置中心的地址
server-addr: ip地址:8848
namespace:
group: SEATA_GROUP
username: nacos
password: nacos
data-id: seataServer.properties
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
preferred-networks: 30.240.*
nacos:
application: seata-server
# 注册中心的地址
server-addr: ip地址:8848
namespace:
group: SEATA_GROUP
username: nacos
password: nacos
cluster: default
store:
# support: file 、 db 、 redis
mode: db
session:
mode: db
lock:
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver # Mysql5.6+ 用 com.mysql.jdbc.Driver 驱动
url: jdbc:mysql://ip地址:3306/seata?useUnicode=true&rewriteBatchedStatements=true
username: 数据库用户名
password: 数据库密码
min-conn: 5
max-conn: 100
global-table: global_table
branch-table: branch_table
lock-table: lock_table
distributed-lock-table: distributed_lock
query-limit: 100
max-wait: 5000
server:
service-port: 8091 #If not configured, the default is '${server.port} + 1000'
max-commit-retry-timeout: -1
max-rollback-retry-timeout: -1
rollback-retry-timeout-unlock-enable: false
enableCheckAuth: true
retryDeadThreshold: 130000
xaerNotaRetryTimeout: 60000
recovery:
handle-all-session-period: 1000
undo:
log-save-days: 7
log-delete-period: 86400000
session:
branch-async-queue-size: 5000 #branch async remove queue size
enable-branch-async-remove: false #enable to asynchronous remove branchSession
# server:
# service-port: 8091 #If not configured, the default is '${server.port} + 1000'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
metrics:
enabled: false
registry-type: compact
exporter-list: prometheus
exporter-prometheus-port: 9898
transport:
rpc-tc-request-timeout: 30000
enable-tc-server-batch-send-response: false
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
boss-thread-size: 1
- 至此,Seata服务端(TC)已经配置并启动成功并注册到nacos了。
- 查看Seata启动日志:
docker logs -f seata-server
配置Seata客户端(TM和RM)
- 引入依赖(
参与分布式事务的每个服务模块中都需要引入下面的依赖
)
<!-- 分布式事务 -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
</dependency>
- undo_log建表、配置参数(仅AT模式)
- https://github.com/seata/seata/blob/1.5.0/script/client/at/db/mysql.sql
- 参与分布式事务的每个服务模块中的数据库都需要新建undo_log表
- 添加yaml配置文件(
参与分布式事务的每个服务模块中都需要引入下面的配置
)
# 分布式事务配置
seata:
tx-service-group: my_test_tx_group
service:
vgroup-mapping:
my_test_tx_group: default
enable-auto-data-source-proxy: true
registry:
type: nacos
nacos:
application: seata-server
server-addr: ip:端口号
namespace:
group: SEATA_GROUP
username: nacos
password: nacos
config:
type: nacos
nacos:
server-addr: ip:端口号
namespace:
group: SEATA_GROUP
username: nacos
password: nacos
dataId: seataServer.properties # 这个名字需要和下面nacos中添加的配置文件名一样
- nacos添加
seataServer.properties
配置文件(group:SEATA_GROUP,需要和服务端的配置文件中配置的group组一样)
#For details about configuration items, see https://seata.io/zh-cn/docs/user/configurations.html
#Transport configuration, for client and server
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableTmClientBatchSendRequest=false
transport.enableRmClientBatchSendRequest=true
transport.enableTcServerBatchSendResponse=false
transport.rpcRmRequestTimeout=30000
transport.rpcTmRequestTimeout=30000
transport.rpcTcRequestTimeout=30000
transport.threadFactory.bossThreadPrefix=NettyBoss
transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
transport.threadFactory.shareBossWorker=false
transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
transport.threadFactory.clientSelectorThreadSize=1
transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
transport.threadFactory.bossThreadSize=1
transport.threadFactory.workerThreadSize=default
transport.shutdown.wait=3
transport.serialization=seata
transport.compressor=none
#Transaction routing rules configuration, only for the client
service.vgroupMapping.my_test_tx_group=default # service.vgroupMapping.后缀 需要和服务端配置 seata:tx-service-group 一致
#If you use a registry, you can ignore it
service.default.grouplist=ip地址:8091 # Seata 服务端地址
service.enableDegrade=false
service.disableGlobalTransaction=false
#Transaction rule configuration, only for the client
client.rm.asyncCommitBufferLimit=10000
client.rm.lock.retryInterval=10
client.rm.lock.retryTimes=30
client.rm.lock.retryPolicyBranchRollbackOnConflict=true
client.rm.reportRetryCount=5
client.rm.tableMetaCheckEnable=true
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.rm.sagaJsonParser=fastjson
client.rm.tccActionInterceptorOrder=-2147482648
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
client.tm.interceptorOrder=-2147482648
client.undo.dataValidation=true
client.undo.logSerialization=jackson
client.undo.onlyCareUpdateColumns=true
server.undo.logSaveDays=7
server.undo.logDeletePeriod=86400000
client.undo.logTable=undo_log
client.undo.compress.enable=true
client.undo.compress.type=zip
client.undo.compress.threshold=64k
#For TCC transaction mode
tcc.fence.logTableName=tcc_fence_log
tcc.fence.cleanPeriod=1h
#Log rule configuration, for client and server
log.exceptionRate=100
#Transaction storage configuration, only for the server. The file, DB, and redis configuration values are optional.
store.mode=db # 存储模式 db
store.lock.mode=file
store.session.mode=file
#Used for password encryption
store.publicKey=
#If `store.mode,store.lock.mode,store.session.mode` are not equal to `file`, you can remove the configuration block.
store.file.dir=file_store/data
store.file.maxBranchSessionSize=16384
store.file.maxGlobalSessionSize=512
store.file.fileWriteBufferCacheSize=16384
store.file.flushDiskMode=async
store.file.sessionReloadReadSize=100
#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.
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver # Mysql5.6+ 用 com.mysql.jdbc.Driver 驱动
store.db.url=jdbc:mysql://ip地址:3306/seata?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
store.db.user=数据库用户名
store.db.password=数据库密码
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.distributedLockTable=distributed_lock
store.db.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
#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.
store.redis.mode=single
store.redis.single.host=127.0.0.1
store.redis.single.port=6379
store.redis.sentinel.masterName=
store.redis.sentinel.sentinelHosts=
store.redis.maxConn=10
store.redis.minConn=1
store.redis.maxTotal=100
store.redis.database=0
store.redis.password=
store.redis.queryLimit=100
#Transaction rule configuration, only for the server
server.recovery.committingRetryPeriod=1000
server.recovery.asynCommittingRetryPeriod=1000
server.recovery.rollbackingRetryPeriod=1000
server.recovery.timeoutRetryPeriod=1000
server.maxCommitRetryTimeout=-1
server.maxRollbackRetryTimeout=-1
server.rollbackRetryTimeoutUnlockEnable=false
server.distributedLockExpireTime=10000
server.xaerNotaRetryTimeout=60000
server.session.branchAsyncQueueSize=5000
server.session.enableBranchAsyncRemove=false
#Metrics configuration, only for the server
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
-
业务使用,全局事务
- 在需要开启全局事务的方法上加上注解
@GlobalTransactional
- 在需要开启全局事务的方法上加上注解
-
启动全局事务对应的业务服务模块,seata服务端可以看到TM和RM的注册日志
注意事项
- AT模式支持的数据库有:MySQL、Oracle、PostgreSQL、 TiDB、MariaDB。当全局事务中有其他数据库(例如:redis等)时,可以将redis等相关删除操作影响事务回滚后的下次执行时,将对应子事务放到全局事务最后面执行。
其它知识
Seata AT 模式
- 两阶段提交协议的演变:
- 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
- 二阶段:
- 提交异步化,非常快速地完成。
- 回滚通过一阶段的回滚日志进行反向补偿。
工作机制
- 以一个示例来说明整个 AT 分支的工作过程。
- AT 分支事务的业务逻辑:
update product set name = 'GTS' where name = 'TXC';
一阶段
-
过程:
- 1.解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = ‘TXC’)等相关的信息。
- 2.查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。
select id, name, since from product where name = 'TXC';
- 3.执行业务 SQL:更新这条记录的 name 为 ‘GTS’。
- 4.查询后镜像:根据前镜像的结果,通过 主键 定位数据。
select id, name, since from product where id = 1;
- 5.插入回滚日志:把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中。
{ "branchId": 641789253, "undoItems": [{ "afterImage": { "rows": [{ "fields": [{ "name": "id", "type": 4, "value": 1 }, { "name": "name", "type": 12, "value": "GTS" }, { "name": "since", "type": 12, "value": "2014" }] }], "tableName": "product" }, "beforeImage": { "rows": [{ "fields": [{ "name": "id", "type": 4, "value": 1 }, { "name": "name", "type": 12, "value": "TXC" }, { "name": "since", "type": 12, "value": "2014" }] }], "tableName": "product" }, "sqlType": "UPDATE" }], "xid": "xid:xxx" }
- 6.提交前,向 TC 注册分支:申请 product 表中,主键值等于 1 的记录的 全局锁 。
- 7.本地事务提交:业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。
- 8.将本地事务提交的结果上报给 TC。
二阶段-回滚
- 收到 TC 的分支回滚请求,开启一个本地事务,执行如下操作。
- 通过 XID 和 Branch ID 查找到相应的 UNDO LOG 记录。
- 数据校验:拿 UNDO LOG 中的后镜与当前数据进行比较,如果有不同,说明数据被当前全局事务之外的动作做了修改。这种情况,需
- 根据配置策略来做处理,详细的说明在另外的文档中介绍。
- 根据 UNDO LOG 中的前镜像和业务 SQL 的相关信息生成并执行回滚的语句:
update product set name = 'TXC' where id = 1;
- 提交本地事务。并把本地事务的执行结果(即分支事务回滚的结果)上报给 TC。
二阶段-提交
- 收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC。
- 异步任务阶段的分支提交请求将异步和批量地删除相应 UNDO LOG 记录。
参考:https://seata.io/zh-cn/
你知道的越多,你不知道的越多。
最后
以上就是默默咖啡为你收集整理的Spring项目整合 Seata分布式事务解决方案的全部内容,希望文章能够帮你解决Spring项目整合 Seata分布式事务解决方案所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复