编程语言
首页 > 编程语言> > SpringCloudAlibaba分布式事务解决方案Seata实战与源码分析-上

SpringCloudAlibaba分布式事务解决方案Seata实战与源码分析-上

作者:互联网

概述

定义

Spring Cloud Alibaba Seata 官网地址 https://seata.io/zh-cn/ 最新版本1.5.2

Spring Cloud Alibaba Seata 文档地址 https://seata.io/zh-cn/docs/overview/what-is-seata.html

Spring Cloud Alibaba Seata GitHub源码地址 https://github.com/seata/seata

Spring Cloud Alibaba Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

image-20220711144621918

事务概念

数据库事务(简称:事务,Transaction)是指数据库执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。事务拥有以下四个特性,习惯上被称为ACID特性,也是指数据库事务正确执行的四个基本要素的缩写包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库,必须要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。

具有ACID的特性的数据库支持强一致性,强一致性代表数据库本身不会出现不一致,每个事务是原子的,或者成功或者失败,事物间是隔离的,互相完全不影响,而且最终状态是持久落盘的,因此,数据库会从一个明确的状态到另外一个明确的状态,中间的临时状态是不会出现的,如果出现也会及时的自动的修复,因此是强一致的。

本地事务与分布式事务

image-20220711140358720

image-20220711140330212

分布式事务理论基础

分布式事务存在两大理论依据: CAP定律和BASE理论;在前面文章《Apache ZooKeeper原理剖析及分布式理论名企高频面试》也有介绍过。BASE 理论是对 CAP 中一致性和可用性权衡的结果,其来源于对大型互联网分布式实践的总结,是基于 CAP 定理逐步演化而来的。其核心思想既然无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

image-20220711141737535

两阶段提交(2PC)

2PC即两阶段提交协议,是将整个事务流程分为两个阶段,P是指准备阶段,C是指提交阶段。

image-20220711143607537

三阶段提交(3PC)

3PC 主要是为了解决两阶段提交协议的单点故障问题和缩小参与者阻塞范围。 是二阶段提交(2PC)的改进版本,引入参与节点的超时机制之外,3PC把2PC的准备阶段分成事务询问(该阶段不会阻塞)和事务预提交,则三个阶段分别为 CanCommit、PreCommit、DoCommit

安装

版本下载

Seata Server作为分布式事务的TC,也即是事务协调者,也是一个Server服务,需要独立部署。Seata Server官网支持多种方式部署:直接部署,使用 Docker, 使用 Docker-Compose, 使用 Kubernetes, 使用 Helm、高可用部署,官网最新版本为1.5.2。我们这里选择直接部署+高可用,先下载官网提供的二进制包。

# 下载最新版本
wget https://github.com/seata/seata/releases/download/v1.5.2/seata-server-1.5.2.tar.gz
# 解压
tar -xvf seata-server-1.5.2.tar.gz
# 进入目录 
cd seata

建议部署结构

官方推荐生产使用的部署结构首先基于Nacos配置中心来管理Seata的配置(事务模式、存储模式如基于DB数据库配置等)、将使用Nacos注册中心将Seata自己注册到Nacos,分布式事务所关联微服务可以通过注册中心感知Seata,实现服务发现和负载均衡等功能,最后将全局协调信息写入数据库,以便多个Seata之间数据共享。

image-20220713110334849

配置数据库

先下载1.5.2的源码 https://github.com/seata/seata/archive/refs/tags/v1.5.2.zip 解压后seata根目录下script\server\db文件下有三类数据库sql脚本。我们选择MySQL的作为数据库因此使用mysql.sql脚本。

image-20220713110635704

创建seata数据库,执行脚本,最新版本1.5.2比之前1.4.x版本很明显多了一张distributed_lock表,原来只有3张

image-20220713110947117

Nacos 配置

为了后面可以结合示例说明,这里使用前面使用simple_ecommerce命令空间,创建seataServer.properties,组为ecom-group

image-20220713111518394

seataServer.properties的配置内容如下,主要是配置db模式及其连接信息

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

service.vgroupMapping.default_tx_group=default
service.default.grouplist=192.168.50.94: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=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

store.mode=db
store.lock.mode=db
store.session.mode=db
store.publicKey=

store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://192.168.50.95:3308/seata?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=123456
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
server.enableParallelRequestHandle=false

metrics.enabled=false
metrics.registryType=compact
metrics.exporterList=prometheus
metrics.exporterPrometheusPort=9898

上面seataServer.properties的内容直接从官网复制过来修改,来自在源码根目录下script\config-center\config.txt

image-20220713113038165

Seata配置

在Seata的conf目录下有application.yml和application.example.yml,application.example.yml是配置样例参考,修改application.yml中config和registry为nacos,详细内容如下:

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

console:
  user:
    username: seata
    password: seata


seata:
  config:
    # support: nacos 、 consul 、 apollo 、 zk  、 etcd3
    type: nacos
    nacos:
      server-addr: 192.168.50.95:8848
      namespace: a2b1a5b7-d0bc-48e8-ab65-04695e61db01
      group: ecom-group
      username: nacos
      password: nacos
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""
      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: 192.168.50.95:8848
      group: ecom-group
      namespace: a2b1a5b7-d0bc-48e8-ab65-04695e61db01
      cluster: default
      username: nacos
      password: nacos
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key: ""
      #secret-key: ""

  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
  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
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

由于前面配置的数据库为MySQL8的版本,而官方打包在target目录下seata-server.jar中包含的mysql-connector-java-5.1.35.jar驱动

image-20220713134840421

因此这里我们拷贝mysql-connector-java-8.0.28.jar到target目录下,并修改bin/seata-server.sh的启动脚本

image-20220713135619330

# 在图中位置增加
JAVA_OPT="${JAVA_OPT} -Xbootclasspath/a:${BASEDIR}/target/mysql-connector-java-8.0.28.jar"
# 启动seata
sh ./bin/seata-server.sh

成功启动,日志中可以看到Seata启动控制台端口7091和Seata提供服务的端口8091(为控制台端口+1000)

image-20220713135515045

访问http://192.168.5.52:7091/端口,用户名密码为seata/seata(在application.yml中配置),登录成功后页面如下

image-20220713135923394

此外Seata的服务也已经注册到Nacos中

image-20220713140236360

**本人博客网站 **IT小神 www.itxiaoshen.com

标签:事务,Seata,数据库,server,源码,client,SpringCloudAlibaba,transport,seata
来源: https://www.cnblogs.com/itxiaoshen/p/16476109.html