(1)理论基础
Seata是 2019 年 1 月份蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。
致力于提供高性能和简单易用的分布式事务服务,为用户打造一站式的分布式解决方案。
官网地址:http://seata.io/,其中的文档、播客中提供了大量的使用说明、源码分析。
Seata架构
Seata事务管理中有三个重要的角色:
TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
Seata提供了四种不同的分布式事务解决方案:
XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
TCC模式:最终一致的分阶段事务模式,有业务侵入
AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
SAGA模式:长事务模式,有业务侵入
【注意:创建seata数据库、创建Seata所需要的数据库表mysql.sql】
事务ACID原则
原子性:事务中的所有操作,要么全部成功,要么全部失败
一致性:要保证数据库内部完整性约束、声明性约束
隔离性:对同一资源操作的事务不能同时发生
持久性:对数据库做的一切修改将永久保存,不管是否出现故障
CAP理论
Consistency(一致性)
Availability(可用性)
Partition tolerance (分区容错性)
分布式系统无法同时满足这三个指标。 这个结论就叫做 CAP 定理。
CAP定理- Consistency
Consistency(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致
CAP定理- Availability
Availability (可用性):用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝
CAP定理-Partition tolerance
Partition(分区):因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。
Tolerance(容错):在集群出现分区时,整个系统也要持续对外提供服务
BASE理论
BASE理论是对CAP的一种解决思路,包含三个思想:
Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。
Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。
而分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论:
AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态
(2)file.conf(数据库配置)
? ? mode = "db"
? ? dbType = "mysql"
? ? driverClassName = "com.mysql.cj.jdbc.Driver"
? ? url = "jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true"
? ? user = "root"
? ? password = "root"
(3)registry.conf(注册中心)
? type = "nacos"
? nacos {
? ? application = "seata-server"
? ? serverAddr = "127.0.0.1:8848"
? ? group = "SEATA_GROUP"
? ? namespace = "48fef45a-f67d-415a-90fa-4beb523011a9"
? ? cluster = "default"
? ? username = "nacos"
? ? password = "nacos"
? }
(4)registry.conf(配置中心)
? type = "nacos"
? nacos {
? ? serverAddr = "127.0.0.1:8848"
? ? namespace = "48fef45a-f67d-415a-90fa-4beb523011a9"
? ? group = "SEATA_GROUP"
? ? username = "nacos"
? ? password = "nacos"
? ? dataId = "seataServer.properties"
? }
(5)nacos配置中心
在之前新创建的命名空间seata_test(48fef45a-f67d-415a-90fa-4beb523011a9)
中创建配置文件
Data ID:seataServer.properties
Group:SEATA_GROUP
配置格式:Properties
修改后的内容如下:
transport.type=TCP
transport.server=NIO
transport.heartbeat=true
transport.enableClientBatchSendRequest=false
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
service.vgroupMapping.zhaoyang_test_tx_group=default
service.default.grouplist=127.0.0.1:8091
service.enableDegrade=false
service.disableGlobalTransaction=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=false
client.rm.tableMetaCheckerInterval=60000
client.rm.sqlParserType=druid
client.rm.reportSuccessEnable=false
client.rm.sagaBranchRegisterEnable=false
client.tm.commitRetryCount=5
client.tm.rollbackRetryCount=5
client.tm.defaultGlobalTransactionTimeout=60000
client.tm.degradeCheck=false
client.tm.degradeCheckAllowTimes=10
client.tm.degradeCheckPeriod=2000
store.mode=db
store.publicKey=
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
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?characterEncoding=utf-8&serverTimezone=Asia/Shanghai&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=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.queryLimit=100
store.db.lockTable=lock_table
store.db.maxWait=5000
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
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
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
log.exceptionRate=100
transport.serialization=seata
transport.compressor=none
metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898
(6)运行
windows系统运行seata-server.bat启动seata即可
Linux系统命令如下:
sh nacos-config.sh -h ip -p 端口 -g 组 -t namespace -u nacos用户名 -w nacos密码
sh nacos-config.sh -h 127.0.0.1 -p 8848 -g SEATA_GROUP -t 48fef45a-f67d-415a-90fa-4beb523011a9 -u nacos -w nacos
(7)项目应用
在需要进行事务控制的子服务所连接的数据库添加表格、回滚SQL
CREATE TABLE `undo_log` (
? `branch_id` bigint(20) NOT NULL COMMENT 'branch transaction id',
? `xid` varchar(128) NOT NULL COMMENT 'global transaction id',
? `context` varchar(128) NOT NULL COMMENT 'undo_log context,such as serialization',
? `rollback_info` longblob NOT NULL COMMENT 'rollback info',
? `log_status` int(11) NOT NULL COMMENT '0:normal status,1:defense status',
? `log_created` datetime(6) NOT NULL COMMENT 'create datetime',
? `log_modified` datetime(6) NOT NULL COMMENT 'modify datetime',
? UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='AT transaction mode undo table';
? ? ? ? <dependency>
? ? ? ? ? ? <groupId>io.seata</groupId>
? ? ? ? ? ? <artifactId>seata-spring-boot-starter</artifactId>
? ? ? ? ? ? <version>1.5.1</version>
? ? ? ? </dependency>
spring:
? datasource:
? ? dynamic:
? ? ? seata: true # 是否启动对 Seata 的集成
seata:
? enabled: true
? enable-auto-data-source-proxy: true #是否开启数据源自动代理,默认为true
? tx-service-group: zhaoyang_test_tx_group? #要与配置文件中的vgroupMapping一致
? registry:? #registry根据seata服务端的registry配置
? ? type: nacos #默认为file
? ? nacos:
? ? ? application: seata-server #配置自己的seata服务
? ? ? server-addr: 127.0.0.1:8848 #根据自己的seata服务配置
? ? ? username: nacos #根据自己的seata服务配置
? ? ? password: nacos #根据自己的seata服务配置
? ? ? namespace: 766c55b9-fa1d-4f3a-aa92-cfbb57445c51 #根据自己的seata服务配置
? ? ? cluster: default # 配置自己的seata服务cluster, 默认为 default
? ? ? group: SEATA_GROUP #根据自己的seata服务配置
? config:
? ? type: nacos
? ? nacos:
? ? ? server-addr: 127.0.0.1:8848 #配置自己的nacos地址
? ? ? group: SEATA_GROUP #配置自己的dev
? ? ? username: nacos #配置自己的username
? ? ? password: nacos #配置自己的password
? ? ? namespace: 766c55b9-fa1d-4f3a-aa92-cfbb57445c51 #配置自己的namespace
? ? ? dataId: seataServer.properties #配置自己的dataId,由于搭建服务端时把客户端的配置也写在了seataServer.properties,所以这里用了和服务端一样的配置文件,实际客户端和服务端的配置文件分离出来更好
数据源注解
@DS("db01")
分布式事务注解
@GlobalTransactional
配置文件信息记录备忘:
dataid:service.vgroupMapping.zhaoyang_test_tx_group
group:SEATA_GROUP
数据:default