Seata基础知识

Seata

学习seata之前,我们先要回顾一下事务和了解一下分布式事务相关的知识,有助于我们理解seata。seata service搭建完成后,使用起来是很简单的。

事务

事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据 库中,一个事务由一组SQL语句组成。事务应该具有4个属性:原子性、一致性、隔离性、持久性。 这四个属性通常称为ACID特性。
任何事务机制在实现时,都应该考虑事务的ACID特性,包括:本地事务、分布式事务,即使不能都很好的满足,也要考虑支持到什么程度。

  • 原子性(Atomicity):事务是一个不可分割的工作单位,事务中包括的诸多操作要么都做,要么都不做。

  • 一致性(Consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态,事务的中间状态不能被观察到的。

  • 隔离性(Isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
    隔离性又分为四个级别:

    • 读未提交(read uncommitted)
    • 读已提交(read committed,解决脏读)
    • 可重复读(repeatable read,解决虚读)
    • 串行化(serializable,解决幻读)
  • 持久性(Durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

分布式事务

完成某一个业务功能可能需要横跨多个服务,操作多个数据库。这就涉及到到了分布式事务,用需要操作的资源位于多个资源服务器上,而应用需要保证对于多个资源服务器的数据的操作,要么全部成 功,要么全部失败。本质上来说,分布式事务就是为了保证不同资源服务器的数据一致性。

典型的分布式事务场景举例:

  • 跨库事务
    一个应用某个功能需要操作多个库,不同的库中存储不同的业务数据 。

  • 分库分表
    通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分 ,也就是分库分表的情况。
    对于分库分表的情况,一般开发人员都会使用一些数据库中间件来降低sql操作的复杂性。如,对 于sql:insert into user(id,name) values (1,“张三”),(2,“李四”)。这条sql是操作单库的语法,单库情 况下,可以保证事务的一致性。但是由于现在进行了分库分表,开发人员希望将1号记录插入分库1,2号记录插入分库2。所以数据库中间件要将其改写为2条sql,分别插入两个不同的分库,此时要保证两个库要不都成功,要不都失败,因此基本上所有的数据库中间件都面临着分布式事务的问题。

  • 服务化
    Service A完成某个功能需要直接操作数据库,同时需要调用Service B和Service C,而Service B又同时操作了2个数据库,Service C也操作了一个库。需要保证这些跨服务的对多个数据库的操作要不都成功,要不都失败。实际上这可能是最典型的分布式事务场景。

常见分布式事务解决方案

解决分布式事务,也有相对应的规范和协议。分布式事务相关的协议有2PC、3PC。由于三阶段提交协议3PC非常难实现,目前市面上主流的分布式事务解决方案都是基于2PC。

  1. seata
  2. 消息队列
  3. saga
  4. XA

他们有一个共同点,都是两阶段提交协议(2PC)。两阶段是指完成整个分布式事务划分成两个步骤完成。上面常见的分布式事务解决方案,分别对应着分布式事务的四种模式:AT、TCC、Saga、XA。 四种分布式事务模式,都有各自的理论基础,分别在不同的时间被提出。每种模式都有它的适用场景,同样每个模式也都诞生有各自的代表产品。而这些代表产品,可能就是我们常见的(全局事务、 基于可靠消息、最大努力通知、TCC)。

2PC两阶段提交协议

2PC(Two-Phase Commit)两阶段提交协议,顾名思义,分为两个阶段:Prepare和Commit

Prepare:提交事务请求

大概流程如下:

在这里插入图片描述

  1. 询问——协调者向所有参与者发送事务请求,询问是否可以执行事务操作,然后等待所有参与者的响应。
  2. 执行——所有参与者接受到协调者事务请求后,所有参与者执行事务操作(例如更新插入等操作),并将Undo和Redo信息记录在事务日志中。
  3. 响应——如果所有参与者成功的执行了事务并写入了Undo和Redo信息,则向协调者返回YES,否则返回NO。此时参与者如果宕机,就不会有任何响应给协调者。

Commit:执行事务提交

执行事务提交分为两种情况,正常提交和中断。

  • 正常提交事务

在这里插入图片描述

  1. commit——协调者向所有参与者发送Commit请求。
  2. 事务提交——参与者收到Commit请求后,执行事务提交,提交完成后释放事务执行期间占有的所有资源。
  3. 反馈结果——参与者执行事务提交后向协调者发送ACK响应。
  4. 完成事务——接收到所有参与者的ACK响应后,完成事务提交。
  • 中断事务

在执行Prepare 步骤过程中,如果某些参与者执行事务失败、宕机或与协调者之间的网络中断,那么协调者就无法 收到所有参与者的YES响应,或者某个参与者返回了 No 响应,此时,协调者就会进入回退流程,对事务进行回 退。流程如下图红色部分(将 Commit 请求替换为红色的 Rollback 请求):

在这里插入图片描述

  1. Rollback——协调者向所有参与者发送 Rollback 请求。
  2. 事务回滚——参与者收到 Rollback 后,使用 Prepare 阶段的Undo日志执行事务回滚,完成后释放事务执行 期占用的所有资源。
  3. 反馈结果——参与者执行事务回滚后向协调者发送 Ack 响应。
  4. 中断事务——接收到所有参与者的ACK响应后,完成事务中断。

2PC的弊端:

  1. 同步阻塞,参与者在等待协调者的指令时,其实是在等待其他参与者的响应,在此过程中,参与者是无法进 行其他操作的,也就是阻塞了其运行。 倘若参与者与协调者之间网络异常导致参与者一直收不到协调者信 息,那么会导致参与者一直阻塞下去。
  2. 单点在2PC中,一切请求都来自协调者,所以协调者的地位是至关重要的,如果协调者宕机,那么就会使参与者一直阻塞并一直占用事务资源。 如果协调者也是分布式,使用选主方式提供服务,那么在一个协调者挂掉后,可以选取另一个协调者继续后续的服务,可以解决单点问题。但是,新协调者无法知道上一个事务的全部状态信息(例如已等待Prepare响应的时长等),所以也无法顺利处理上一个事务。
  3. 数据不一致,Commit事务过程中Commit请求/Rollback 请求可能因为协调者宕机或协调者与参与者网络问题丢失,那么就导致了部分参与者没有收到Commit/Rollback请求,而其他参与者则正常收到执行了Commit/Rollback 操作,没有收到请求的参与者则继续阻塞。这时,参与者之间的数据就不再一致了。 当参与者执行Commit/Rollback后会向协调者发送ACK,然而协调者不论是否收到所有的参与者的ACK,该事务也不会再有其他补救措施了,协调者能做的也就是等待超时后像事务发起者返回一个“我不确定该事务是否成 功”。
  4. 环境可靠性依赖协调者Prepare请求发出后,等待响应,然而如果有参与者宕机或与协调者之间的网络中断,都会导致协调者无法收到所有参与者的响应,那么在 2PC 中,协调者会等待一定时间,然后超时后, 会触发事务中断,在这个过程中,协调者和所有其他参与者都是出于阻塞的。这种机制对网络问题常见的现实环境来说太苛刻了。

AT、TCC、Saga、XA四种事务模式

  • AT模式(Auto Transcation)
    AT模式是一种无侵入的分布式事务解决方案。阿里的seata框架实现了该模式。在AT模式下,用户只需要关注自己的业务SQL,用户的业务SQL作为一阶段,seata框架会自动生成事务的二阶段提交和回滚操作。

在这里插入图片描述

一阶段:

在一阶段,Seata会拦截“业务 SQL”,首先解析SQL语义,找到“业务 SQL”要更新的业务数据,在业务数据被更新前,将其保存成“before image”,然后执行“业务 SQL”更新业务数据, 在业务数据更新之后,再将其保存成“after image”,最后生成行锁。以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。

在这里插入图片描述

二阶段提交:

二阶段如果是提交的话,因为“业务 SQL”在一阶段已经提交至数据库, 所以Seata框架只需将一 阶段保存的快照数据和行锁删掉,完成数据清理即可。

在这里插入图片描述

二阶段回滚:

二阶段如果是回滚的话,Seata就需要回滚一阶段已经执行的“业务 SQL”,还原业务数据。回滚方式便是用“before image”还原业务数据。但在还原前要首先要校验脏写,对比“数据库当前业务数据”和 “after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一 致就说明有脏写,出现脏写就需要转人工处理。

在这里插入图片描述

AT模式的一阶段、二阶段提交和回滚均由Seata框架自动生成,用户只需编写“业务 SQL”,便能轻松接入分布式事务,AT 模式是一种对业务无任何侵入的分布式事务解决方案。

  • TCC模式(Try Commit Cancel)
    TCC模式入侵性比较强,并且得自己实现相关事务控制逻辑。但是,在整个过程中基本没有锁,所以性能更强。

    常见的TCC模式框架:BeyeTCC、TCC-transction、Himly

    TCC模式需要用户根据自己的业务场景实现Try、Confirm和Cancel三个操作。事务发起方在一阶段执行Try方式,在二阶段提交执行Confirm方法,二阶段回滚执行Cancel方法。
    在这里插入图片描述

    TCC 三个方法描述:

    • Try:资源的检测和预留

    • Confirm:执行的业务操作提交。要求Try成功Confirm一定要能成功

    • Cancel:预留资源释放

  • Saga模式
    补偿协议:业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者。一阶段正向服务和二阶段补偿服务都由业务开发实现。
    saga模式的实现,是长事务解决方案。saga是一种补偿协议,在saga模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
    在这里插入图片描述

    如图:T1-Tn都是正向业务流程,都对应着一个冲正逆向操作C1-C3

    逻辑如下:分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。 Saga 正向服务与补偿服务也需要业务开发者实现。因此是业务入侵的。 Saga 模式下分布式事务通常是由事件驱动的,各个参与者之间是异步执行的,Saga 模式是一种长事务解决方案。

    saga模式适用场景
    Saga模式适用于业务流程长且需要保证事务最终一致性的业务系统,Saga模式一阶段就会提交本地事务,无锁、长流程情况下可以保证性能。 事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供TCC要求的接口,可以使用 Saga 模式。

    saga模式的优缺点

    优点:

    • 一阶段提交本地数据库事务,无锁,高性能
    • 参与者可以采用事务驱动异步执行,高吞吐
    • 补偿服务即正向服务的“反向”,易于理解,易于实现

    缺点:

    ​ Saga模式由于一阶段已经提交本地数据库事务,且没有进行“预留”动作,所以不能保证隔离性。

  • XA模式
    在XA模式下,需要有一个[全局]协调器,每一个数据库事务完成后,进行第一阶段预提交,并通知协调器,把结果给协调器。协调器等所有分支事务操作完成、都预提交后,进行第二步。第二步协调器通知每个数据库进行逐个commit/rollback。其中,这个全局协调器就是XA模型中的TM角色,每个分支事务各自的数据库就是RM。

    XA模式缺点:事务粒度大。高并发下,系统可用性低。因此很少使用。

AT、TCC、Saga、XA 四种模式总结

四种分布式事务模式,分别在不同的时间被提出,每种模式都有它的适用场景。

  • AT模式是无侵入的分布式事务解决方案,适用于不希望对业务进行改造的场景,几乎0学 习成本。

  • TCC模式是高性能分布式事务解决方案,适用于核心系统等对性能有很高要求的场景。

  • Saga 模式是长事务解决方案,适用于业务流程长且需要保证事务最终一致性的业务系统, Saga 模式一阶段就会提交本地事务,无锁,长流程情况下可以保证性能,多用于渠道层、集成层业务系统。事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供TCC要求的接口,也可以使用 Saga 模式。

  • XA模式是分布式强一致性的解决方案,但性能低而使用较少。

分布式事务本身就是一个技术难题,业务中具体使用哪种方案还是需要不同的业务特点自行选择。但是,我们也会发现,分布式事务会大大的提高流程的复杂度,会带来很多额外的开销工作(代码量上 去了,业务复杂了,性能下跌了)。 所以,当我们真实开发的过程中,能不使用分布式事务就不使用。

Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata将为用户提供了 AT、TCC、Saga 和 XA 事务模式,AT模式是阿里首推的模式 。

相关官方文档:

官网:https://seata.io/zh-cn/index.html

源码: https://github.com/seata/seata

官方Demo: https://github.com/seata/seata-samples

Seata相关设计

在 Seata 的架构中,一共有三个角色。其中,TC为单独部署的Server服务端,TM和RM为嵌入到应用中的 Client 客户端。

  1. TC (Transaction Coordinator) - 事务协调者
    维护全局和分支事务的状态,驱动全局事务提交或回滚。

  2. TM (Transaction Manager) - 事务管理器
    定义全局事务的范围:开始全局事务、提交或回滚全局事务。

  3. RM (Resource Manager) - 资源管理器
    管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

在 Seata 中,一个分布式事务的生命周期如下:

在这里插入图片描述

  1. TM请求TC开启一个全局事务。TC 会生成一个XID作为该全局事务的编号。XID会在微服务的调用链路中传播,保证将多个微服务的子事务关联在一起。 当一进入事务方法中就会生成XID。global_table表中就是存储的全局事务信息

  2. RM请求TC将本地事务注册为全局事务的分支事务,通过全局事务的XID进行关联。当运行数据库操作方法,branch_table表中存储事务参与者信息

  3. TM请求TC告诉XID对应的全局事务是进行提交还是回滚。

  4. TC驱动RM们将XID对应的自己的本地事务进行提交还是回滚。

设计思路

AT模式的核心是对业务无入侵,是一种改进后的二阶段提交。设计思路如下:

第一阶段

业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。核心在于对业务sql进行解析,转换成undolog,并同时入库。

在这里插入图片描述

第二阶段

分布式事务操作成功,则TC通知RM异步删除undolog

在这里插入图片描述

分布式事务操作失败,TM向TC发送回滚请求,RM收到协调器TC发来的回滚请求,通过XID和Branch ID找到相应的回滚日志记 录,通过回滚记录生成反向的更新SQL并执行(执行前会将before image和after image进行对比),然后删除事务占用的资源。完成分支的回滚。

在这里插入图片描述

设计亮点

  1. 应用层基于SQL解析实现了自动补偿,从而最大程度的降低业务侵入性。
  2. 将分布式事务中TC(事务协调者)独立部署,负责事务的注册、回滚。
  3. 通过全局锁实现了写隔离与读隔离。

存在的问题

  • 性能损耗

    一条Update的SQL,则需要全局事务xid获取(与TC通讯)、before image(解析SQL,查询一次数据库)、after image(查询一 次数据库)、insert undo log(写一次数据库)、before commit(与TC通讯,判断锁冲突),这些操作都需要一次远程通讯RPC,而且是同步的。另外undo log写入时blob字段的插入性能也是不高的。每条写SQL都会增加这么多开销,粗略估计会增加5倍响应时间。

  • 性价比

    为了进行自动补偿,需要对所有交易生成前后镜像并持久化,可是在实际业务场景下,这个是成功率有多高,或者说分布式事务失败需要回滚的有多少比率?按照二八原则预估,为了20%的交易回滚,需要将80%的成功交易的响应时间增加5倍,这样的代价相比于让应用开发一个补偿交易是否是值得?

  • 热点数据

    相比XA,Seata虽然在一阶段成功后会释放数据库锁,但一阶段在commit前全局锁的判定也拉长了对数据锁的占有时间,这个开销比XA的prepare低多少需要根据实际业务场景进行测试。全局锁的引入实现了隔离性,但带来的问题就是阻塞,降低并发性,尤其是热点数据,这个问题会更加严重。

  • 回滚锁释放时间

    Seata在回滚时,需要先删除各节点的undo log,然后才能释放TC内存中的锁,所以如果第二阶段是回滚,释放锁的时间会更长。

  • 死锁问题

    Seata的引入全局锁会额外增加死锁的风险,但如果出现死锁,会不断进行重试,最后靠等待全局锁超时,这种方式并不优雅,也延长了对数据库锁的占有时间。

Seata使用

使用Seata需要单独部署Seata的服务,配置中心等。在服务中也需要创建相关表。相关构建可能会有点复杂,但是用是需要使用一个@GlobalTransaction注解就好。

这次是在本地win上搭建,在linux上搭建需要修改的配置文件和win差不多。后期有机会再在linux上部署一下。

Seata Server(TC)搭建

Seata服务端下载地址:

https://github.com/seata/seata/releases

结合自己项目的spring cloud alibaba版本选择合适的Seata版本。我这边使用的是seata-server-1.3.0

在这里插入图片描述

下载完成后,解压即可。接下来就是修改配置了。

修改Server端存储模式(store.mode)

Server端支持三种存储模式:

  1. file:默认模式,单机模式。全局事务会话信息存在内存中,读写并持久化到本地文件root.data中。性能较高。
  2. db:要求mysql5.7+,高可用模式。全局事务会话信息通过db共享,性能稍差一些。
  3. redis:Seata-Server1.3及以上斑斑支持,性能较高,但是存在事务信息丢失的风险。建议提前配置适当的当前场景的redis持久化配置。

这边使用db模式演示,具体操作如下:

  • 修改seata\conf\file.conf文件
    在这里插入图片描述

  • 创建数据库
    根据上一步中的配置文件中的配置,建立对应的数据库
    在这里插入图片描述

  • 创建表

数据库脚本可以在官方文档——>运维指南——>部署——>新人文档——>资源目录介绍,点击查看处获取。注意这里部署的是server端。

https://github.com/seata/seata/blob/1.4.0/script/server/db/mysql.sql
在这里插入图片描述

Seata整合nacos
  • 整合注册中心

    说明:这两项配置可以更改负载均衡模式

    loadBalance = “RandomLoadBalance”

    loadBalanceVirtualNode = 10

    loadBalanceVirtualNode = 10

在这里插入图片描述

  • 整合配置中心

在这里插入图片描述

注意:如果seata-server使用了nacos作为配置中心,配置信息就会从nacos中读取。配置registry.conf使用nacos时,group配置要和seata-server中的group一样。

  • 修改seata配置中心信息

    先从seata官网(https://github.com/seata/seata/tree/1.4.0)获取seata源码工程的压缩文件,然后获取seata-1.4.0\script\config-center\config.txt并修改部分配置

在这里插入图片描述

seata-1.4.0\script\config-center\config.txt文件中的一些说明:

service.vgroupMapping.my_test_tx_group=default
  1. 使用了seata的客户端需要和my_test_tx_group保存一致。my_test_tx_group也可以自定义为guangzhou、shanghai等这样根据服务器地域进行命名(本次配置中使用的是"service.vgroupMapping.guangzhou=default"),可以用作异地灾备的一个配置。那么对应的客户端就要如下配置

    spring.cloud.alibaba.seata.tx_service_group=guangzhou
    
  2. default需要等于registry.confi中registry配置中的cluster对应的值
    在这里插入图片描述

  • 同步配置参数到nacos

    在seata-1.4.0\script\config-center\nacos下运行以下脚本

    sh nacos-config.sh -h 192.168.2.7 -p 8848 -g SEATA_GROUP -t 8375c8f1-32d7-4d34-80f0-4ff80378c437 -u nacos -w nacos
    # 相关参数说明:
    # -h nacos主机host,默认值localhost
    # -p nacos服务port,默认值8848
    # -g 配置的分组,默认值SEATA_GROUP
    # -t 租户信息,对应nacos中的namespaceID 默认为nacos的public
    # -u nacos登录名,需要有读写权限
    # -w 对应登录名的密码
    

在这里插入图片描述

然后就可以在nacos配置中心看到这些配置。

在这里插入图片描述

  • 启动seata-server服务
seata/bin/seata-server.sh -h 127.0.0.1 -p 8091 -m db -n 1 -e test

参数说明:

参数全写作用备注
-h–host指定在注册中心中注册的IP不指定时获取当前的IP,外部访问部署在云环境和容器中时建议指定
-p–port指定server启动的端口默认为8091
-m–storeMode事务日志存储方式支持file,db,redis(需要seata-server1.3+)。默认为file
-n–serverNode用于指定seata-server节点ID如1,2,3,…默认为1
-e–seataEvn指定seate-server运行环境如dev,test等,服务启动时会使用registry-dev.conf这样的配置

集群部署:

seata集群的方式在win下不是很好部署。在linux下部署很方便,因为它不像nacos一样还需使用nginx来负载,seata直接使用nacos的LB。

# 机器1
seata/bin/seata-server.sh -h 127.0.0.1 -p 8091 -m db -n 1 -e test
# 机器2
seata/bin/seata-server.sh -h 127.0.0.1 -p 8092 -m db -n 2 -e test
# 机器3
seata/bin/seata-server.sh -h 127.0.0.1 -p 8093 -m db -n 3 -e test

双击seata\bin下seata-server.bat启动Seata server。

在这里插入图片描述

在启动seata server服务时遇到了一个Could not create connection to database server报错,已经解决了,可移步查看

使用seata

下面的操作都是基于上一步的部署成功的seata server服务中进行。

  • 添加依赖
    在使用到分布式事务的服务pom文件下添加seata依赖。

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    </dependency>
    
  • 创建undo_log表
    在使用到分布式事务的服务对应的数据库中添加undo_log表,脚本如下:

CREATE TABLE `undo_log` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `branch_id` bigint(20) NOT NULL,
    `xid` varchar(100) NOT NULL,
    `context` varchar(128) NOT NULL,
    `rollback_info` longblob NOT NULL,
    `log_status` int(11) NOT NULL,
    `log_created` datetime NOT NULL,
    `log_modified` datetime NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
  ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  • 添加配置文件
    在使用到分布式事务的服务配置文件中添加seata相关配置。

    # 数据源
    spring:
      datasource:
        username: root
        password: password
        url: jdbc:mysql://localhost:3306/seata_order?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
    
        #初始化时运行sql脚本
        schema: classpath:sql/schema.sql
        initialization-mode: never
      application:
        name: alibaba-order-seata
      cloud:
        nacos:
          discovery:
            server-addr: 192.168.2.7:8848
            username: nacos
            password: nacos
        alibaba:
          seata:
            tx-service-group: guangzhou #配置事务分组 看下自己配置中心的事务分组名称是啥
    #设置mybatis
    mybatis:
      mapper-locations: classpath:com/kiwi/order/mapper/*Mapper.xml
      #config-location: classpath:mybatis-config.xml
      typeAliasesPackage: com.kiwi.order.pojo
      configuration:
        mapUnderscoreToCamelCase: true
    server:
      port: 8072
    seata:
      registry:
        # 配置seata的注册中心, 告诉seata client 怎么去访问seata server(TC)
        type: nacos
        nacos:
          server-addr: 192.168.2.7:8848  # seata server 所在的nacos服务地址
          application: seata-server    # seata server 的服务名seata-server ,如果没有修改可以不配
          username: nacos
          password: nacos
          group: SEATA_GROUP          # seata server 所在的组,默认就是SEATA_GROUP,没有改也可以不配
          namespace: 8375c8f1-32d7-4d34-80f0-4ff80378c437 # 自己seata注册中心namespace
      config:
        type: nacos
        nacos:
          server-addr: 192.168.2.7:8848
          username: nacos
          password: nacos
          group: SEATA_GROUP
          namespace: 8375c8f1-32d7-4d34-80f0-4ff80378c437  # 自己seata配置中心namespace
    
  • 使用@GlobalTransaction注解
    在存在分布式事务的方法上添加@GlobalTransaction注解。

    @GlobalTransactional
        @Override
        public Order create(Order order) {
            // 插入能否成功?
            orderMapper.insert(order);
    
            // 扣减库存 能否成功?
            stockService.reduct(order.getProductId());
    
            // 异常
            int a=1/0;
    
            return order;
        }
    

启动服务,测试发生异常的回滚效果:

接口是访问不了

在这里插入图片描述

控制台报错

在这里插入图片描述

库存服务数据库数据未扣减,分布式事务生效。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值