基于Seata+Nacos分布式事务方案实战
概念介绍
含义解释
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简单来说就是软件系统有了多个不同的数据源,这些数据源不仅地理位置不同,保存的数据内容也会不同,并且每个业务操作都涉及对多个数据源的修改,此时分布式事务就保证这些对数据源的修改要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证分布式系统中的**单个业务操作对多个数据源**的修改都能符合最终的预期。
*举例来说*: 在分布式系统中,往往有多个服务集群,每个服务集群有各自的数据源集群,比如订单服务集群+订单数据库集群,库存服务集群+库存数据库集群等等,一次下订单的业务操作涉及对订单服务集群、库存服务集群的操作,分布式事务是为了保证做了下订单操作后,订单服务集群的订单
信息、库存服务的库存信息都能正确更新(或者失败后能回滚恢复)。
典型框架
+ Alibaba-Seata
+ Seata基于XA,TCC等理论实现分布式事务功能。
实战使用
以Alibaba的Seata框架来进行分布式事务实战
核心原理
-
分布式架构(Seata)
- TC: 事务协调器,用于接受RM的反馈结果,并基于结果通知TM事务成功或失败的处理逻辑
- TM: 事务管理器,用于通知RM进行事务提交或者回滚操作
- RM: 资源管理器,相当于各个微服务的本地事务,主要用于接收TM的事务管理通知,并向TC反馈事务状态、结果
-
分布式事务方案
- XA-eXtended Architect
- TCC-Try Confirm Cancel-三阶段
实战(SpringBoot+Seata+Nacos)
Nacos部署
-
在指定的Docker文件目录创建conf、data、logs等文件夹(用于后续作文件夹映射)
-
部署(docker)
docker run -d -p 8848:8848 -v X:\XX\group-distributed-transaction\nacos\conf:/home/nacos/conf -v X:\XX\group-distributed-transaction\nacos\logs:/home/nacos/logs -v X:\XX\group-distributed-transaction\nacos\data:/home/nacos/data --name nacos-server nacos/nacos-server:latest
- seata.properties配置事务group
- 在运行的nacos下的public命名空间下创建seata.properties,Group填DEFAULT-GROUP
service.vgroupMapping.order-service-tx-group=default service.vgroupMapping.account-service-tx-group=default service.vgroupMapping.business-service-tx-group=default service.vgroupMapping.storage-service-tx-group=default
- 在运行的nacos下的public命名空间下创建seata-server.properties,Group填DEFAULT-GROUP
service.vgroupMapping.default-tx-group=default store.mode=db store.lock.mode=db store.session.mode=db #---所包围的配置需根据自己的情况去填写 store.db.datasource=druid store.db.dbType=mysql store.db.driverClassName=com.mysql.cj.jdbc.Driver store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true #---所包围的配置需根据自己的情况去填写 store.db.user=root store.db.password=root 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 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 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 tcc.fence.logTableName=tcc_fence_log tcc.fence.cleanPeriod=1h log.exceptionRate=100 metrics.enabled=false metrics.registryType=compact metrics.exporterList=prometheus metrics.exporterPrometheusPort=9898 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
Seata部署
- 访问https://github.com/apache/incubator-seata/releases 下载最新的seata版本包并解压
- 修改seata的application.yml配置文件,作如下改动
seata:
# 修改seata的配置中心-主要是用于获取动态的seata配置文件seata-server.properties
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: public
group: DEFAULT_GROUP
username:
password:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key: ""
#secret-key: ""
data-id: seata-server.properties
# 修改seata的注册中心-主要是将seata服务注册为nacos下的seata-server服务,给微服务的分布式业务调用
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: DEFAULT_GROUP
namespace: public
cluster: default
username:
password:
##if use MSE Nacos with auth, mutex with username/password attribute
#access-key: ""
#secret-key: ""
# 修改seata的数据库配置,需提前创建seata数据库以及相关分布式事务表,创建表的sql路径:spring-cloud-alibaba开源项目的spring-cloud-alibaba-examples\seata-example\all.sql
store:
# support: file 、 db 、 redis
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
user: root
password: root
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'
security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
- Windows运行seata\bin下的seata-server.bat启动seata服务,可在nacos上确认服务是否成功注册。
微服务分布式事务实战(待更新)
主要是参考alibaba开源项目spring-cloud-alibaba下的spring-cloud-alibaba-examples\seata-example子项目
-
业务服务 bussiness-service: 主要是基于seata调用其他几个服务的事务流程接口,实现分布式事务
-
库存服务 storage-service:
-
账号服务 account-service
-
订单服务 order-service
FAQ
-
Docker+Seata启动报错"com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure"
- 检查数据库地址、用户密码、ClassDriver版本等等
-
Windows10 Docker安装seata+nacos,nacos上注册的seata-server ip宿主机无法访问,尝试配置SEATA-IP\修改docker网络模式都无效,微服务一直报错无法访问nacos下的ip为192.17.0.2的seata-server
- 可能是windows下docker的网桥功能有问题,容器能访问宿主机ip,但反向则不行,后续采用本地运行seata程序的方法解决该问题;