zoukankan      html  css  js  c++  java
  • Seata解决方案整体介绍

    1.SEATA是什么:

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

    2、SEATA整体框架:

         Seata 中有三大模块,分别是 TM、RM 和 TC。其中 TM 和 RM 是作为 Seata 的客户端与业务系统集成在一起,TC 作为 Seata 的服务端独立部署。

     

    角色划分:

    TM事务管理器,开启、 提交、回滚分布式事务

    RM: 资源管理器,注册、 汇报、执⾏资源

    TC :  事务管理器服务功能,存储事务日志、补偿异常事务等、集中管理事务全局锁(全局行锁),seata服务端

    事务执行整体流程:

    • TM 开启分布式事务(TM 向 TC 注册全局事务记录);
    • 按业务场景,编排数据库、服务等事务内资源(RM 向 TC 汇报资源准备状态 );
    • TM 结束分布式事务,事务一阶段结束(TM 通知 TC 提交/回滚分布式事务);
    • TC 汇总事务信息,决定分布式事务是提交还是回滚;
    • TC 通知所有 RM 提交/回滚 资源,事务二阶段结束;

    3、AT模式介绍

    AT 模式是一种无侵入的分布式事务解决方案。在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。

    1、 整体机制:

       两阶段提交协议的演变:

       一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。

       二阶段:

      • 提交异步化,非常快速地完成。
      • 回滚通过一阶段的回滚日志进行反向补偿。

    2、详细流程:

    一阶段提交:

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

     二阶段提交

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

     二阶段回滚:

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

     3、并发事务的隔离处理:  

      写隔离:

           正常提交:

          tx1先开启本地事务,拿到本地锁; tx1更新操作 m = 1000-100 = 900; tx1拿到记录的全局行锁 ; tx1本地提交,释放本地锁  tx2开启本地事务,拿到本地锁; tx2更新操作 m = 900-100 = 800。 tx2尝试拿该记录的全局行锁; tx2重试等待全局锁 (tx1全局提交前,全局锁被 tx1 持有)  tx1全局提交,释放全局锁; tx2拿到记录的全局行锁; tx2本地提交,释放本地锁; tx2全局提交,释放全局行锁。

        数据回滚:

          tx1获得全局锁,二阶段全局回滚,需获取本地锁; tx2持有本地锁,等待全局行锁。  tx1分支回滚失败,一直重试;  tx2等待全局行锁超时; tx2回滚本地事务,释放本地锁; tx1获取本地锁,回滚成功。 tx1全局回滚,释放全局行, 整个过程全局锁一直被 tx1 持有,所以不会发生脏写的问题。

       读隔离:

           AT 模式默认全局隔离级别是读未提交 。如果应用在特定场景下,必需全局读已提交,Seata方式是通过 SELECT FOR UPDATE 语句代理。  SELECT FOR UPDATE 语句执行会自动申请全局行锁,如果全局锁被其他事务持有,则释放本地锁(回滚 SELECT FOR UPDATE 语句的本地执行)并重试。  这个过程中,查询是被 block 住的,直到全局行锁拿到,即读取的相关数据是已提交的才返回。

    4、适用场景:

       分布式事务的业务逻辑中仅仅纯数据库操作,不包含其他中间件事务逻辑。

       优势:

       改动及代码侵入最小。由Seata来负责Commit和Rollback的自动化触发或回滚操作。

       劣势

       1、如果事务中包含缓存存储或发送EQ消息等不适合。

       2、为了保证镜像sql的可靠性,需要用户对sql尽量做简化, 建议做法:将多条SQL语句分解为多个事务中的原子步骤(对应SeataAt模式的分支Branch概念),如果单条SQL语句跨表,也分解成为多个事务中的原子步骤(尽量降低Seata存储镜前SQL结果时的风险)。

       3、多次对DB的操作,以及全局行锁的存在对并发处理性能有影响。

    4、TCC模式介绍

     该模式由蚂蚁金服贡献。TCC 模式需要用户根据自己的业务场景实现 Try、Confirm 和 Cancel 三个操作;事务发起方在一阶段执行 Try 方式,在二阶段提交执行 Confirm 方法,二阶段回滚执行 Cancel 方法。

    整体流程图:

    TCC 三个方法描述:

    • Try:资源的检测和预留;
    • Confirm:执行的业务操作提交;要求 Try 成功 Confirm 一定要能成功;
    • Cancel:预留资源释放;

    TCC典型业务场景分析:

    转账场景:A账户扣钱,B账户加钱;

    账户 A 上有 100 元,要扣除其中的 30 元 :

           如上图所示,Try 方法作为一阶段准备方法,需要做资源的检查和预留。

          在扣钱场景下,Try 要做的事情是就是检查账户余额是否充足,预留转账资金,预留的方式就是冻结 A 账户的 转账资金。Try 方法执行之后,账号 A 余额虽然还是 100,但是其中 30 元已经被冻结了,不能被其他事务使用。         二阶段 Confirm 方法执行真正的扣钱操作。Confirm 会使用 Try 阶段冻结的资金,执行账号扣款。Confirm 方法执行之后,账号 A 在一阶段中冻结的 30 元已经被扣除,账号 A 余额变成 70 元 。

          如果二阶段是回滚的话,就需要在 Cancel 方法内释放一阶段 Try 冻结的 30 元,使账号 A 的回到初始状态,100 元全部可用。

    TCC 设计要点:

       允许空回滚:

        状态: try未执行,收到cancel请求

        原因:

               Try超时(网络丢包)---->分布式事务回滚,触发cancel---->未收到try,收到cancel

        解决方案:

        Cancel 接口设计时需要允许空回滚。在 Try 接口因为丢包时没有收到,事务管理器会触发回滚,这时会触发         Cancel 接口,这时 Cancel 执行时发现没有对应的事务 xid 或主键时,需要返回回滚成功。让事务服务管理器       认为已回滚。

         

        防悬挂控制:

          状态:Cancel比Try先执行

       

         原因:

              Try超时(网络拥堵)------> 分布式事务回滚,触发cancel----->拥堵的Try到达

        解决方案:

        首先Cancel 接口设计时需要允许空回滚。在 Cancel 空回滚返回成功之前先记录该条事务 xid 或业务主键,标识这条记录已经回滚过,Try 接口先检查这条事务xid或业务主键如果已经标记为回滚成功过,则不执行Try 的业务操作。

       幂等处理:

         Try、Confirm、Cancel三个方法均要保证幂等性。

    TCC适用场景:

         分布式事务的业务逻辑中除了数据库操作外,包含其他中间件事务逻辑。

    优势:

        1、用户可以自己定义业务的补偿逻辑,由业务层保证事务的一致性;

        2、适合微服务化场景;

        3、无 AT 模式的全局行锁,TCC 性能会比 AT 模式高很多。

    劣势:

         1、需要考虑如何将业务模型拆成 2 阶段,实现成 TCC 的 3 个方法,并且保证 Try 成功 Confirm 一定能成功,Confirm失败会不断重试。

         2、TCC 模式下开发者需要自行实现try,confirm,cancel接口,对业务代码有一定的侵入性。

     

    4、Seata的saga模式

    Saga 模式介绍:

          Saga 模式是Seata的长事务解决方案,由蚂蚁金服主要贡献。在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。

    Saga模式机制:

         

          分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会去退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。

           Saga 模式下分布式事务通常是由事件驱动的,各个参与者之间是异步执行的,Saga 模式是一种长事务解决方案。

    Saga设计要点:

    允许空补偿:

          状态:原服务未执行,补偿服务执行了。

          原因:

                  原服务超时(丢包)---> Saga事务触发回滚 ---->  未收到原服务的请求,先收到补偿请求。

          解决方案:允许空补偿。

    防悬挂控制

           状态:补偿服务比原服务先执行。

           原因:

                    原服务超时(网络拥堵)-----> Saga事务回滚-----> 先进行补偿操作以后,拥堵的原服务到达。

          解决方案:允许空回滚,拒绝空回滚以后原服务的执行。

    幂等控制:

          原服务和补偿服务支持幂等操作。

    自定义事务恢复策略:

          1、Saga事务不保证隔离性,在极端情况下会出现由于脏写导致无法完成回滚补偿操作,此时状态机引擎可以“重试”继续往前完成这个分布式事务。由于整个业务流程是由状态机编排的,即使是事后恢复也可以继续往前重试。

         2、 用户可以基于业务特点配置该流程的事务处理策略是优先“回滚”还是“重试”,当事务超时,seata会基于用户配置的策略不断进行重试。

    使用建议:

            由于 Saga 不保证隔离性,所以我们在业务设计的时候需要做到“宁可长款,不可短款”的原则,长款是指在出现差错的时候站在我方的角度钱多了的情况,钱少了则是短款,因为如果长款可以给客户退款,而短款则可能钱追不回来了,也就是说在业务设计的时候,一定是先扣客户帐再入帐,如果因为隔离性问题造成覆盖更新,也不会出现钱少了的情况。

    适用场景:

          1、长流程事务、不需马上返回最终结果,只要保证最终一致性的场景,

          2、对数据隔离性要求不高,对性能要求高的场景。

          3、事务参与者可能是其它公司的服务或者是遗留系统的服务,无法进行改造和提供 TCC 要求的接口。

    优势:

          事件驱动、无全局锁、异步、高吞吐、性能高,补偿易实现。

    劣势:

          自己写补偿逻辑,没有事务隔离性。

     

  • 相关阅读:
    窗体吸附 Timer + 判断Location (简单实用)
    C# FTP 应用程序
    C# 加密方法汇总
    LINQ 标准的查询操作符 合计操作符 Count()、Sum()、Min()、Max()、Average()和Aggregate()
    委托中的协变和逆变(C# 编程指南)
    深入探讨C#序列化和反序列化
    grep 命令详解
    Oracle 数据库的启动和关闭的方式!
    linux 下的光盘拷贝
    C3P0连接池配置
  • 原文地址:https://www.cnblogs.com/anhaogoon/p/13033611.html
Copyright © 2011-2022 走看看