Seata的使用

Seata

Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。

术语

  1. TC(Transaction Coordinator) -事务协调者(相当于服务端)

    1. 维护全局和分支事务的状态,驱动全局事务提交或回滚

  2. TM(Transaction Manager) - 事务管理器(相当于应用,相当于各模块)

    1. 定义全局事务的范围:开始全局事务,提交或回滚全局事务

  3. RM(Resource Manager) - 资源管理器(数据库)

    1. 管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

seata分布式事务原理

以官方示例为例,

老项目正常流程:当我们采用分布式部署时,Order下单后,Account账户中扣除数据完成后,再调用Storage库存减一。

但是现在数据库分开,那么Order完成后就直接完成数据库的修改,接着到Account中扣除金额完成,返回到business中,调用storage减除库存时发现库存不足,但是前两步已经提交了。

如果不做分布式事务的话我们就要重新提供接口,在进行反向的操作,例如Account中需要将金额加上。

问题:调度事情就很多,补偿很多,以及还有可能补偿失败。

  • 这里就交给Seata来做,我们来写补偿。由seata来具体操作,这就是Seata的TCC模式。

  • 补偿也不由我们来写,由Seata自动分析来进行,比如update金额减少之后,发现需要重新操作,这是Seata就会自动生产sql,update金额加回来。这就是Seata中的AT模式

分布式事务的四种模式

  • AT模式:默认,简单,需要增加undo_log表,生产反向SQL,性能高。回滚后,原来没数据的,现在还是没数据

  • TCC模式:try confirm/cancel ,三个阶段代码都得自己实现,Seata只负责调度。对业务代码入侵性较强,必要时可能还要修改数据库(因为try并非真正的去扣减,而是做一个冻结的操作,比如100:有我们需要扣减一,就会冻结一个,接着在confirm中解冻,真正去扣减)

  • SAGA模式,长事务解决方案,需要程序员自己编写两阶段代码(AT模式不需要写第二阶段)

    • 基于状态机实现,需要一个JSON文件,可异步执行

  • XA模式,XA协议是由X/Open组织提出的分布式事务处理规范,基于数据库的XA协议来实现2PC又称为XA方案,适用于强一致性的场景,比如金融、银行

Seata应用 :

选中座位后事务处理,座位表修改售卖情况sell(b库),余票详情表修改余票(b库),为会员增加购票记录(会员端的接口),更新确定订单为成功(b库)

  1. 引入依赖:

  2. 需要使用分布式事务的都增加undo表。

  3. 配置每个模块

  4. 开启分布式事务,@GlobalTransactional

注:统一异常处理:

需要判断是否为全局事务。如果不加这段member出现异常时,虽然commonResp.success=false但是接口返回码是200,business会认为调用是成功的。

配置中心

seata有自己的配置中心,需要重新配置,而springcloud中的配置仅仅作用于项目。注册中心同理。

修改配置中心与注册中心:在conf目录下的application.yml中参照application.example.yml进行配置

从配置中心中配置文件

与自己设置保持一致

配置好数据库,以及基本的表,可在script/server/db下找到mysql.sql执行。

注:AT模式会有一个全局锁,用来防止脏读,线程1的事务修改了库存,但是还没有提交事务,线程二读库存读的还是原来的库存。

在配置中心定义所有的项目所属的集群,当集群挂了可以快速换成另一个集群。

sql限制:

Seata 事务目前支持 INSERT、UPDATE、DELETE 三类 DML 语法的部分功能,这些类型都是已经经过Seata开源社区的验证。SQL 的支持范围还在不断扩大,建议在本文限制的范围内使用。如果您有意帮助社区支持更多类型的SQL,请提交PR申请。

  • 不支持 SQL 嵌套

  • 不支持多表复杂 SQL(自1.6.0版本,MySQL支持UPDATE JOIN语句,详情请看 )

  • 不支持存储过程、触发器

  • 部分数据库不支持批量更新,在使用 MySQL、Mariadb、PostgreSQL9.6+作为数据库时支持批量,批量更新方式如下以 Java 为例

 // use JdbcTemplate
    public void batchUpdate() {
        jdbcTemplate.batchUpdate(
            "update storage_tbl set count = count -1 where id = 1",
            "update storage_tbl set count = count -1 where id = 2"
        );
    }
​
•    // use Statement
•    public void batchUpdateTwo() {
•        statement.addBatch("update storage_tbl set count = count -1 where id = 1");
•        statement.addBatch("update storage_tbl set count = count -1 where id = 2");
•        statement.executeBatch();
•    }

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值