Spring Cloud之Seata的学习

这篇具有很好参考价值的文章主要介绍了Spring Cloud之Seata的学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

案例准备

分布式事务

基本理论

CAP定理

BASE理论

Seata

部署TC服务

数据库准备

修改Nacos配置并导入信息

启动Seata

集成Seata

XA模式原理

Seata的XA实现

优点

缺点

实现

AT模式原理

AT模式的脏写问题

Seata的AT实现

XA与AT的区别

TCC模式原理

空回滚与业务悬挂问题

Seata的TCC实现

Saga模式原理

四种模式对比

高可用


案例资料下载地址:day02分布式事务

案例准备

  1. 将资料中的seata-demo.sql文件加载到数据库中。
  2. seata-demo文件夹使用IDEA打开。
  3. 启动nacos与所有微服务
  4. 测试订单,发送POST请求

观察数据库

Spring Cloud之Seata的学习,spring cloud,学习,微服务

Spring Cloud之Seata的学习,spring cloud,学习,微服务

成功添加一个订单。

分布式事务

在分布式系统下,一个业务跨越多个服务或数据源,每个服务都是一个分支事务。要保证所有的分支事务最终状态保持一致,这样的事务就是分布式事务。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

基本理论

CAP定理

所谓CAP是指:

  • Consistency(一致性)
  • Availability(可用性)
  • Partition tolerance(分区容错性)

分布式系统无法同时满足这三个指标。当分区出现时系统的一致性和可用性无法同时满足。

一致性:用户访问分布式系统中的任意节点,得到的数据必须一致

Spring Cloud之Seata的学习,spring cloud,学习,微服务

可用性:用户访问集群中任意健康节点,必须得到相应,而不是超时或拒绝

Spring Cloud之Seata的学习,spring cloud,学习,微服务

分区容错:所谓分区,就是因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。而容错,就是在集群出现分区时,整个系统也要持续对外提供服务

Spring Cloud之Seata的学习,spring cloud,学习,微服务

BASE理论

BASE理论是对CAP的一种解决思路

  • Basically Available(基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用
  • Soft state(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态
  • Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。

而分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论:

  • AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致。
  • CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。

比如ES集群就属于CP,当ES集群一个节点网络故障时,会被剔除,该节点的数据分片会被保存在其他节点上。保证了高一致性,低可用性。所以是CP。

Seata

Seata事务管理中存在三个角色:

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

Spring Cloud之Seata的学习,spring cloud,学习,微服务

Seata提供了四种不同的分布式事务解决方案:

  • XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
  • TCC模式:最终一致的分阶段事务模式,有业务侵入
  • AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式
  • SAGA模式:长事务模式,有业务侵入

部署TC服务

下载Seata:GitHub - seata/seata: :fire: Seata is an easy-to-use, high-performance, open source distributed transaction solution.

需要注意的是,最新版本与1.5.0之前的Seata配置方式不同,这里我采用的是1.7.1版本。资料中的版本也有对应的文本文件。

数据库准备

sql文件保存在该目录下\script\server\db。在数据库中执行sql文件。

修改Nacos配置并导入信息

修改文件\seata\conf\application.yml

Spring Cloud之Seata的学习,spring cloud,学习,微服务

在Nacos创建配置文件

Spring Cloud之Seata的学习,spring cloud,学习,微服务

将路径\script\config-center\config.txt修改如下内容后全选粘贴到nacos中的配置内容处

Spring Cloud之Seata的学习,spring cloud,学习,微服务

启动Seata

双击启动bin目录下的seata-server.bat

访问地址http://localhost:7091/#/login

默认用户名与密码都为seata

nacos控制台可以看到seata的节点

Spring Cloud之Seata的学习,spring cloud,学习,微服务

集成Seata

引入依赖

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.4.2</version>
        </dependency>

配置文件添加如下内容

seata:
  registry:
    # nacos配置
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: DEFAULT_GROUP
      namespace: seata-demo
      username: nacos
      password: nacos
  tx-service-group: seata-demo #事务组名称
  #如果seata是一个集群,那么在nacos寻找seata节点时,就要这么去配置
  service:
    vgroup-mapping: #事务组与cluster的映射关系
      seata-demo: SH

seata客户端发现seata集群中的节点,需要tx-service-group中的值作为key,vgroup-mapping作为value的映射关系去寻找。

XA模式原理

是强一致性的事务。基于数据库本身特性实现的

Spring Cloud之Seata的学习,spring cloud,学习,微服务

Spring Cloud之Seata的学习,spring cloud,学习,微服务

Seata的XA实现

Spring Cloud之Seata的学习,spring cloud,学习,微服务

RM一阶段的工作:

  • 注册分支事务到TC
  • 执行分支业务sql但不提交
  • 报告执行状态到TC

TC二阶段的工作:

  • TC检测各分支事务执行状态
    • 如果都成功,通知所有RM提交事务
    • 如果有失败,通知所有RM回滚事务

RM二阶段的工作:

  • 接收TC指令,提交或回滚事务
优点
  • 强一致性
  • 基于数据库做了一层封装,实现简单
缺点
  • 如果关联的事务较多,且耗时较长,已经执行完毕的事务还需要等待其他事务完成,耗费资源更大,性能差。
  • 依赖关系数据库实现,如果使用Redis则不适用
实现

修改配置文件。该配置作用是对数据源做代理,拦截所有sql请求,RM帮我们调用数据库的XA接口。

seata:
  data-source-proxy-mode: XA

给全局事务的入口方法添加注解@GlobalTransactional注解(和Transactional注解添加位置一样)

@GlobalTransactional
public Long create(Order order) {
	// 创建订单
	orderMapper.insert(order);
	try {
    	// 扣用户余额
    	accountClient.deduct(order.getUserId(), order.getMoney());
    	// 扣库存
    	storageClient.deduct(order.getCommodityCode(), order.getCount());

	} catch (FeignException e) {
    	log.error("下单失败,原因:{}", e.contentUTF8(), e);
    	throw new RuntimeException(e.contentUTF8(), e);
	}
	return order.getId();
}

接下来测试一个一定失败的新增订单请求

Spring Cloud之Seata的学习,spring cloud,学习,微服务

查看数据库发现,库存没有减少,用户金额也没扣减,订单也没增加。观察控制台输出,是扣款之后再回滚

Spring Cloud之Seata的学习,spring cloud,学习,微服务

AT模式原理

AT模式同样是分阶段提交事务模型。不过弥补了XA模型中资源锁定周期过长的缺陷。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

阶段一RM工作:

  • 注册分支事务
  • 记录undo-log(快照)
  • 执行sql并提交
  • 报告事务状态

阶段二提交时RM的工作:删除undo-log

阶段二回滚时RM的工作:根据undo-log恢复数据到更新前

AT模式的脏写问题

Spring Cloud之Seata的学习,spring cloud,学习,微服务

出现脏写的情况是因为事务没有做到隔离,为了解决这个问题,引入了全局锁概念。TC记录当前正在操作某行数据的事务,该事务持有全局锁,具有执行权。主要记录的是事务id、事务操作的表名、以及该表的被修改的数据主键值。Spring Cloud之Seata的学习,spring cloud,学习,微服务

需要注意的是。这里存在两个锁,一个是数据库的DB锁一个是Seata管理的全局锁。为了避免死锁问题,通常全局锁在等待300毫秒内还没有获取到锁就进行超时回滚。比DB锁超时时间要短很多。

由于全局锁只会对被Seata管理的事务生效,对普通事务不生效。因此,可能存在普通事务修改数据的可能,导致Seata管理的事务进行回滚时造成的脏写事件。对此,AT模式不光会保存修改前的数据快照(before-image),也会保存修改后的数据快照(after-image)。当进行回滚时,会对数据库当前的数据与修改后的数据库快照(after-image)进行对比。如果发现不一样,则说明在回滚之前期间有其他事务修改了数据。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

Seata的AT实现

将资料中的seata-at.sql文件以文本方式打开。里面有两张表的创建语句。将lock_table表(管理全局锁的表)创建语句在TC服务的数据库中执行。undo_log表(快照存放表,由RM管理)在微服务访问的数据库中创建。

修改配置文件中的事务模式为AT

seata:
  data-source-proxy-mode: AT

重启服务后,发送一次库存不足的请求观察是否扣减余额和创建订单。

可以看到,执行了扣款操作,但是根据快照回滚并将快照信息删除。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

XA与AT的区别

XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源

XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚

XA模式强一致;AT模式最终一致

TCC模式原理

TCC模式与AT模式非常相似,每阶段都是独立事务,不同的是TCC通过人工编码来实现数据恢复。需要实现三个方法:

  • Try:资源的检测和预留
  • Confirm:完成资源操作业务;要求Try 成功 Confirm 一定要能成功。
  • Cancel:预留资源释放,可以理解为try的反向操作。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

阶段一进行资源预留。阶段二不管是提交还是回滚,都是对自己预留部分的操作。不需要像XA模式加锁或是AT模式一样保存数据快照。在性能上比前两种模式更好一些。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

TCC模式的优点:

  • 一阶段完成直接提交事务,释放数据库资源,性能好
  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库

TCC模式的缺点:

  • 有代码侵入,需要人为编写try、Confirm和Cancel接口,麻烦
  • 软状态,事务是最终一致
  • 需要考虑Confirm和Cancel的失败情况,做好幂等处理

空回滚与业务悬挂问题

当某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就是空回滚。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

而对于已经空回滚的业务,如果后续阻塞的事务恢复,继续执行try,就永远不可能confire或cancel,这就是业务悬挂。应当阻止执行空回滚后的try操作,避免悬挂。

Seata的TCC实现

TCC实现资源冻结通常是新加一张表,被冻结的资源放在该表中,根据该表信息来执行Cancel

Try业务:

  • 记录冻结金额和事务状态到account_freeze表
  • 扣减account表可用金额

Confirm业务:根据xid删除account_freeze表的冻结记录

Cancel业务:

  • 修改account_freeze表冻结金额为0,state为2
  • 修改account表,恢复可用金额

如何判断是否空回滚:cancel业务中,根据xid查询account_freeze,如果为null则说明try还没做,需要空回滚。

如何避免业务悬挂:try业务中,根据xid查询account_freeze ,如果已经存在则证明Cancel已经执行,拒绝执行try业务

将资料中的account_freeze_tbl.sql文件在微服务访问的数据库执行。

编写Java业务代码

@LocalTCC
public interface AccountTCCService {
    //该注解在哪个方法上就说明哪个方法为try方法,name值要和方法名一样
    @TwoPhaseBusinessAction(name="deduct",commitMethod = "confirm",rollbackMethod = "cancel")
    void deduct(@BusinessActionContextParameter(paramName = "userId") String userId,//参数中的注解会被加载到BusinessActionContext中。
                @BusinessActionContextParameter(paramName = "money") int money);

    boolean confirm(BusinessActionContext ctx);

    boolean cancel(BusinessActionContext ctx);
}
@Service
public class AccountTCCServiceImpl implements AccountTCCService {
    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private AccountFreezeMapper accountFreezeMapper;

    @Override
    public void deduct(String userId, int money) {
        //获取全局事务ID
        String xid = RootContext.getXID();
        AccountFreeze accountFreeze = accountFreezeMapper.selectById(xid);
        if (accountFreeze!=null){
            //已经执行过Cancel,不去执行
            return;
        }
        //扣减用户余额
        accountMapper.deduct(userId, money);
        //冻结表新增余额
        accountFreeze = new AccountFreeze();
        accountFreeze.setXid(xid);
        accountFreeze.setUserId(userId);
        accountFreeze.setFreezeMoney(money);
        accountFreeze.setState(AccountFreeze.State.TRY);
        accountFreezeMapper.insert(accountFreeze);
    }

    @Override
    public boolean confirm(BusinessActionContext ctx) {
        //提交事务,删除该表全局事务对应的数据就可以
        String xid = ctx.getXid();
        int count = accountFreezeMapper.deleteById(xid);
        return count == 1;
    }

    @Override
    public boolean cancel(BusinessActionContext ctx) {
        //判断是否为空回滚
        String xid = ctx.getXid();
        String userId = ctx.getActionContext("userId").toString();
        int money = (int) ctx.getActionContext("money");
        AccountFreeze accountFreeze = accountFreezeMapper.selectById(xid);
        if (accountFreeze == null) {
            //是空回滚
            accountFreeze = new AccountFreeze();
            accountFreeze.setXid(xid);
            accountFreeze.setUserId(userId);
            accountFreeze.setFreezeMoney(money);
            accountFreeze.setState(AccountFreeze.State.CANCEL);
            accountFreezeMapper.insert(accountFreeze);
            return true;
        }
        // 幂等处理
        if (accountFreeze.getState() == AccountFreeze.State.CANCEL) {
            return true;
        }
        //说明不是空回滚,恢复数据
        accountMapper.refund(userId, money);
        accountFreeze.setState(AccountFreeze.State.CANCEL);
        accountFreeze.setFreezeMoney(0);
        int count = accountFreezeMapper.updateById(accountFreeze);
        return count == 1;
    }
}

修改Controller代码,装配TCCService的bean对象。重启服务,再次发送一次库存不足请求

Spring Cloud之Seata的学习,spring cloud,学习,微服务

Saga模式原理

Saga模式是Seata提供的长事务解决方案。也分为两个阶段

一阶段:直接提交本地事务

二阶段:成功什么也不用做,失败通过编写补偿业务进行回滚

由于TCC是通过预留资源实现业务提交或回滚,而Saga是直接对资源本身进行操作,因此不存在事务隔离性,有一定安全问题。

优点:

  • 事务参与者可以基于事件驱动实现异步调用,吞吐高
  • 一阶段直接提交事务,无锁,性能好
  • 不同编写TCC中的三个阶段

缺点:

  • 软状态持续时间不确定,时效性差
  • 没有锁,没有事务隔离,会存在脏写问题

Spring Cloud之Seata的学习,spring cloud,学习,微服务

通常不适用该模式,通常使用AT模式,使用TCC或XA做补充

四种模式对比

XA

AT

TCC

SAGA

一致性

强一致

弱一致

弱一致

最终一致

隔离性

完全隔离

基于全局锁隔离

基于资源预留隔离

无隔离

代码入侵

要编写三个接口

要编写状态机和补偿业务

性能

很好

很好

场景

对一致性、隔离性有高要求的业务

基于关系型数据库的大多数分布式场景都可以

对性能要求较高的事务。有非关系型数据库要参与的事务

业务流程长,业务流程多。参与者包含其他公司或遗留系统服务,无法提供TCC模式要求的三个接口

高可用

TC服务作为Seata的核心服务,一定要保证高可用和异地容灾。接下来我们对Seata进行集群配置

将原来seata文件复制一份作为第二个节点

修改第二份文件集群名称。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

接着启动2号节点

seata-server.bat -p 8092

接下来,我们需要将tx-service-group与cluster的映射关系都配置到nacos配置中心,方便生产环境下实现热更新部署。

Spring Cloud之Seata的学习,spring cloud,学习,微服务

微服务读取nacos配置文件

seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      username: nacos
      password: nacos
      group: SEATA_GROUP
      data-id: client.properties

启动微服务观察

Spring Cloud之Seata的学习,spring cloud,学习,微服务

所有服务都注册到SH集群节点上。

修改nacos中的配置信息

Spring Cloud之Seata的学习,spring cloud,学习,微服务

实现了动态切换集群

Spring Cloud之Seata的学习,spring cloud,学习,微服务文章来源地址https://www.toymoban.com/news/detail-742780.html

到了这里,关于Spring Cloud之Seata的学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Seata TCC 模式下解决幂等、悬挂、空回滚问题 | Spring Cloud56

    通过以下系列章节: docker-compose 实现Seata Server高可用部署 | Spring Cloud 51 Seata AT 模式理论学习、事务隔离及部分源码解析 | Spring Cloud 52 Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53 Seata XA 模式理论学习、使用及注意事项 | Spring Cloud54 Seata TCC 模式理论学习、生产级

    2024年02月09日
    浏览(30)
  • 【Spring Cloud Alibaba Seata 处理分布式事务】——每天一点小知识

                                                                                   💧 S p r i n g C l o u d A l i b a b a S e a t a 处理分布式事务 color{#FF1493}{Spring Cloud Alibaba Seata 处理分布式事务} Sp r in g Cl o u d A l ibaba S e a t a 处理分布式事务 💧

    2024年02月12日
    浏览(40)
  • 【spring cloud学习】4、创建服务提供者

    注册中心Eureka Server创建并启动之后,接下来介绍如何创建一个Provider并且注册到Eureka Server中,再提供一个REST接口给其他服务调用。 首先一个Provider至少需要两个组件包依赖:Spring Boot Web服务组件和Eureka Client组件。如下所示: Spring Boot Web服务组件用于提供REST接口服务,Eure

    2024年02月11日
    浏览(37)
  • 【spring cloud学习】2、Eureka服务注册与发现

    一套微服务架构的系统由很多单一职责的服务单元组成,而每个服务单元又有众多运行实例。由于各服务单元颗粒度较小、数量众多,相互之间呈现网状依赖关系,因此需要服务注册中心来统一管理微服务实例,维护各服务实例的健康状态。 从宏观角度,微服务架构下的系统

    2024年02月10日
    浏览(69)
  • 【合集】Spring Cloud 组件——架构进化史话 & Eureka,Nacos,OpenFeign,Ribbon,Sentinel,Gateway ,Seata+事务. . .

    Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,集群状态)。 注意: 首先,尽管Spring Cloud带有“Cloud”这个单词,但它并不是云计算解

    2024年02月08日
    浏览(40)
  • 【合集】Spring Cloud 组件——架构进化史话 & Eureka,Nacos,Apollo,OpenFeign,Ribbon,Sentinel,Gateway ,Seata+事务. . .

    Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,集群状态)。 注意: 首先,尽管Spring Cloud带有“Cloud”这个单词,但它并不是云计算解

    2024年02月03日
    浏览(179)
  • 微服务 Spring Cloud 5,一图说透Spring Cloud微服务架构

    大家好,我是哪吒。 很多人都说现在是云原生、大模型的时代,微服务已经过时了,但现实的是,很多人开发多年,都没有在实际的开发中用过微服务,更别提搭建微服务框架和技术选型了。 面试的时候都会问,怎么办? 今天分享一张微服务的丐版架构图,让你可以和面试

    2024年02月05日
    浏览(52)
  • 【spring cloud学习】1、spring cloud入门

    Spring Cloud全家桶是Pivotal团队提供的一整套微服务开源解决方案,包括服务注册与发现、配置中心、全链路监控、服务网关、负载均衡、熔断器等组件。以上组件主要是通过对Netflix OSS套件中的组件整合而成的,该开源子项目叫作spring-cloud-netflix, 其中比较重要的组件有: (

    2024年02月11日
    浏览(47)
  • 【Spring Cloud】如何确定微服务项目的Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本

    本文描述如何确定微服务项目的Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本。 我们知道Spring Boot、Spring Cloud、Spring Cloud Alibaba的版本选择一致性非常重要。在选择Spring Boot和Spring Cloud版本时,需要考虑到两者之间的关系以及项目的具体需求。 首先,Spring Boot和Spring Cloud有密切

    2024年02月08日
    浏览(58)
  • 【微服务学习】spring-cloud-starter-stream 4.x 版本的使用(rocketmq 版)

    @[TOC](【微服务学习】spring-cloud-starter-stream 4.x 版本的使用(rocketmq 版)) 2.1 消息发送者 2.1.1 使用 StreamBridge streamBridge; 往指定信道发送消息 2.1.2 通过隐式绑定信道, 注册 Bean 发送消息 2.2 消息接收者 注意: 多个方法之间可以使用 “|” 间隔, 但是绑定时 多个需要按顺序写. 其中

    2024年02月03日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包