数据库中间件:Seata

(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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容