分布式事务解决方案Seata谁建议你用的?

分布式事务解决方案Seata谁建议你用的?_第1张图片

一、名词解释:

 TC (Transaction Coordinator) - 事务协调者

维护全局/分支事务的状态,驱动全局事务的提交与回滚

TM (Transaction Manager) - 事务管理器

定义全局事务的范围:开启、提交、回滚全局事务

RM (Resource Manager) - 资源管理器

管理分支事务(本地事务)与TC交互,注册、报告分支事务状态,管理分支事务的提交、回滚

二、seata支持的模式

1、AT

如上图如果使用的是AT模式,需要在每个DB创建一个UNDO_LOG 表,把业务Sql和前后镜像SQL租出一条回滚记录插入该表

整体机制

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

        二阶段:分支事务全部成功,异步提交(删除回滚日志);分支事务有失败,通过一阶段的回滚日志进行补偿

注意点:

        1、t1,t2两个线程操作一条数据,t1分支事务提交前会获取全局事务,如果t1不释放全局事务,t2分支事务提交时获取全局锁会等待,直到t1全局事务是否或者t2超时退出

        2、AT中每个分支事务都是独立的,只要不更新同一条数据就没什么关系,即便发生更新同一条数据也只会在真正提交的时候等待全局事务,t1,t2几乎是并行的

        3、t2一阶段正持有本地锁并且等待获取全局锁;t1第二阶段回滚,需要获取本地锁,这个时候就出现了循环等待的情况(也就是我们常说的死锁条件),这个时候为了避免脏写,需要t2获取全局锁超时,释放本地锁,t1获取到本地锁执行回滚补偿

具体过程

  1. 解析 SQL:得到 SQL 的类型(UPDATE),表(product),条件(where name = 'TXC')等相关的信息。
  2. 查询前镜像:根据解析得到的条件信息,生成查询语句,定位数据。--一次查询
  3. 执行业务 SQL:更新这条记录的 name 为 'GTS'。-- 一条update
  4. 查询后镜像:根据前镜像的结果,通过 主键 定位数据。--一次查询
  5. 插入回滚日志:把前后镜像数据以及业务 SQL 相关的信息组成一条回滚日志记录,插入到 UNDO_LOG 表中。--一条insert
  6. 提交前,向 TC 注册分支:申请 product 表中,主键值等于 1 的记录的 全局锁 。
  7. 本地事务提交:业务数据的更新和前面步骤中生成的 UNDO LOG 一并提交。--一次更新(3和5一次本地事务提交)
  8. 将本地事务提交的结果上报给 TC。

期间多了两次查询,一条insert语句,比直接更新效率低了不止一倍

2、TCC

        1、需要业务编写prepare ,commit,rollback

        2、全局管理分支事务,不存在等待,需要自己维护业务逻辑(比如维护一个中间态,扣款的时候先冻结)

3、saga

        1、每个业务都需要单独实现数据的正向操作和逆向操作

        2、如果分支业务都正常,事务结束;如果分支业务异常,可正向或逆向补偿

4、XA

        1、执行业务前先获取全局事务,不存在分支事务情况

        2、t1未释放全局事务之前,t2一直等待或者超时

        3、最长得等时间=最长的分支RM

三、总结:

AT和XA

1、AT不需要单独配置,XA方式一:要求开发者配置 XADataSource,方式二:根据开发者的普通 DataSource 来创建但需要创建出相应的 XAConnection

2、AT分支事务单独管理释放,XA需要等待每个分支事务都释放(所有的分支事务时间依赖于最长的分支事务)

3、AT需要建UNDO_LOG表记录回滚日志,XA不需要建表

TCC和Saga

1、TCC需要实现三个接口,Saga业务维护状态通过补偿实现一致性

总体来说:

1、TCC,Saga需要业务代码侵入,并且是每个业务都要写一套

2、XA对接简单,并发量支持有限

3、AT如果链路较长,更新频繁,也可能存在等待时间较长

题外话:saga是不是有点像平时写代码不要事务,用job或MQ做最终一致性的样子

你可能感兴趣的:(分布式)