概述

定义

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 事务模式,为用户打造一站式的分布式解决方案。

  • TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,驱动全局事务提交或回滚。
  • TM (Transaction Manager) - 事务管理器:定义全局事务的范围:开始全局事务、提交或回滚全局事务。
  • RM (Resource Manager) - 资源管理器:管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

事务概念

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

  • 原子性(Atomicity)

    • 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • 一致性(Consistency)
    • 事务前后数据的完整性必须保持一致。转账 A:1000 B:1000 转 200 事务成功 A:800 B:1200
  • 隔离性(Isolation)
    • 事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,一个事务在执行过程中不能看到其他事务运行过程的中间状态,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离,通过配置事务隔离级别可以避免脏读、重复读等问题。
  • 持久性(Durability)
    • 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

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

本地事务与分布式事务

  • 本地事务:简单理解就是整个服务(不是整个项目,而是该微服务)只操作单一数据源如同一服务器同一MySQL数据库。事务仅限于对单一数据库资源的访问控制,架构服务化以后,事务的概念延伸到了服务中。倘若将一个单一的服务操作作为一个事务,那么整个服务操作只能涉及一个单一的数据库资源,这类基于单个服务单一数据库资源访问的事务,被称为本地事务(Local Transaction)。

  • 分布式事务:分布式事务指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上,且属于不同的应用,分布式事务需要保证这些操作要么全部成功,要么全部失败。

    • 随着互联网的发展,从之前的单一项目逐渐向分布式服务做转换,现如今微服务在各个公司已经普遍存在,而当时的本地事务已经无法满足分布式应用的要求,因此分布式服务之间事务的协调就产生了问题,如果做到多个服务之间事务的操作,能够像本地事务一样遵循ACID原则也成为难题。
    • 本质上来说,分布式事务就是为了保证不同数据库的数据一致性;较之基于单一数据库资源访问的本地事务,分布式事务的应用架构更为复杂。在不同的分布式应用架构下,实现一个分布式事务要考虑的问题并不完全一样,比如对多资源的协调、事务的跨服务传播等,实现机制也是复杂多变。

分布式事务理论基础

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

  • Basically Available(基本可用):保证核心业务是可以使用,至于其他业务可以适当降低响应时间甚至是服务降级。假设系统,出现了不可预知的故障,但还是能用,相比较正常的系统而言:

    • 响应时间上的损失:正常情况下的搜索引擎 0.5 秒即返回给用户结果,而基本可用的搜索引擎可以在 1 秒作用返回结果。
    • 功能上的损失:在一个电商网站上,正常情况下,用户可以顺利完成每一笔订单,但是到了大促期间,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。

  • Soft state(软状态):相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种 “硬状态”。软状态指的是:允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许系统在多个不同节点的数据副本存在数据延时。
  • Eventually consistent(最终一致性):系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问最终都能够获取到最新的值。

两阶段提交(2PC)

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

  • 准备阶段(Prepare phase):事务管理器给每个参与者发送 Prepare消息,每个数据库参与者在本地执行事务,并写本地的 Undo/Redo日志,此时事务没有提交。

    • undo日志是记录修改前的数据,用于数据库回滚。
    • Redo日志是记录修改后的数据,用于提交事务写入数据文件。
  • 提交阶段(commit phase):如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者发送(Rollback) 消息,如果收到参与者都成功,发送(Commit) 参与者根据事务管理器的指令执行提交或者回滚操作,并释放事务处理过程中使用的资源。

    • 执行事务成功提交

    • 执行事务失败回滚

三阶段提交(3PC)

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

  • 3PC是2PC的升级版,引入了超时机制,解决了单点故障引起的事务阻塞问题,但是3PC依然不能解决事务一致性的问题,因为在DoCommit阶段,如果由于网络或者超时等原则导致参与者收不到协调者发送过来的 中断事务消息(abort) ,过了这个时间后,参与者会提交事务,本来是应该进行回滚,提交事务后,会导致数据不一致的问题出现
  • 2PC虽然在网络故障情况下存在强一致性被破坏的问题,但是故障恢复以后能保证最终一致性,3PC虽然有超时时间,解决了阻塞,提高了可用性,但是牺牲了一致性,如果针对网络波动问题导致数据问题这一点上,2PC是优于3PC的。

安装

版本下载

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之间数据共享。

配置数据库

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

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

Nacos 配置

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

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

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驱动

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

# 在图中位置增加
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)

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

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

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

SpringCloudAlibaba分布式事务解决方案Seata实战与源码分析-上的更多相关文章

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

    事务模式 概述 在当前的技术发展阶段,不存一个分布式事务处理机制可以完美满足所有场景的需求.一致性.可靠性.易用性.性能等诸多方面的系统设计约束,需要用不同的事务处理机制去满足. 目前使用的流行度情况 ...

  2. SpringCloudAlibaba分布式流量控制组件Sentinel实战与源码分析(上)

    概述 定义 Sentinel官网地址 https://sentinelguard.io/zh-cn/index.html 最新版本v1.8.4 Sentinel官网文档地址 https://senti ...

  3. SpringCloudAlibaba分布式流量控制组件Sentinel实战与源码分析-中

    实战示例 控制台初体验 Sentinel的控制台启动后,控制台页面的内容数据都是空的,接下来我们来逐步操作演示结合控制台的使用,在上一节也已说明整合SpringCloud Alibaba第一步先加入s ...

  4. SpringCloud Gateway微服务网关实战与源码分析-上

    概述 定义 Spring Cloud Gateway 官网地址 https://spring.io/projects/spring-cloud-gateway/ 最新版本3.1.3 Spring Cl ...

  5. SpringCloudGateway微服务网关实战与源码分析 - 中

    实战 路由过滤器工厂 路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应.路由过滤器的作用域是特定的路由.SpringCloud Gateway包括许多内置的GatewayFilter ...

  6. 从flink-example分析flink组件(3)WordCount 流式实战及源码分析

    前面介绍了批量处理的WorkCount是如何执行的 <从flink-example分析flink组件(1)WordCount batch实战及源码分析> <从flink-exampl ...

  7. 分布式事务解决方案Seata

    Seata全称是Simple Extensible Autonomous Transaction Architecture,是由阿里巴巴开源的具有高性能和易用性的分布式事务解决方案. 微服务中的分布式 ...

  8. 分布式事务中间件 Fescar—RM 模块源码解读

    前言 在SOA.微服务架构流行的年代,许多复杂业务上需要支持多资源占用场景,而在分布式系统中因为某个资源不足而导致其它资源占用回滚的系统设计一直是个难点.我所在的团队也遇到了这个问题,为解决这个问题上 ...

  9. SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...

随机推荐

  1. 三月总结&四月计划

    三月总结 1. 主要任务 <C++设计模式>网课 ① 进展: 看完,对设计模式的整体设计思路和几个重要的设计模式重点学习了一下,目前对设计模式的认识还比较浅 ② 总结: 做完总结 ③ 反思 ...

  2. Java 16 新特性:instanceof增强

    instanceof这个关键词,主要用来判断某个对象是不是某个类的实例. 比如,有时候我们要处理一个类似这样的数据集: Map<String, Object> data = new Has ...

  3. spring 拦截器流程 HandlerInterceptor AsyncHandlerInterceptor HandlerInterceptorAdapter

    HandlerInterceptor源码 3种方法: preHandle:拦截于请求刚进入时,进行判断,需要boolean返回值,如果返回true将继续执行,如果返回false,将不进行执行.一般用于 ...

  4. 关于Spring中的useSuffixPatternMatch

    背景 spring-boot的版本是2.1.4.RELEASE,spring的版本是5.1.6.RELEASE 一个例子如下: @Configuration @Import(WebMvcAutoCon ...

  5. CentOS6安装PLEX

    CentOS6安装PLEX 一.安装使用PLEX 1.1 安装 1)下载 https://www.plex.tv/downloads/ plexmediaserver-1.11.3.4803-c40b ...

  6. 源码解读etcd heartbeat,election timeout之间的拉锯

    转一个我在知乎上回答的有关raft election timeout/ heartbeat interval 的回答吧. 答:准确来讲: election是timeout,而heartbeat 是in ...

  7. Navicat可视化MySQL数据库

    Navicat可视化MySQL数据库 Navicat内部封装了所有的操作数据库的命令,用户只需要点击操作即可,无需书写sql语句. navicat能够充当多个数据库的客户端. 具体操作参考百度. py ...

  8. Java命令行传递参数

    目录 命令行传参 代码运行 视频 命令行传参 有时候你希望运行一个程序的时候再传递给它消息. 这要靠传递命令行参数给main()函数实现 package com.broky.base; public ...

  9. 学学dotnet core中的身份验证和授权-1-概念

    前言 身份验证: Authentication 授权: Authorization net core 中的身份验证和授权这两个部分,是相辅相成的.当初我在学在部分的时候,是看的 net core 官网 ...

  10. Docker搭建大数据集群 Hadoop Spark HBase Hive Zookeeper Scala

    Docker搭建大数据集群 给出一个完全分布式hadoop+spark集群搭建完整文档,从环境准备(包括机器名,ip映射步骤,ssh免密,Java等)开始,包括zookeeper,hadoop,hiv ...