Java重要面试名词整理(十九):Seata

文章目录

分布式事务概述

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

实现思路:两阶段提交协议(2PC)

两阶段提交(Two Phase Commit),就是将提交(commit)过程划分为2个阶段(Phase):

阶段1:

TM(事务管理器)通知各个RM(资源管理器)准备提交它们的事务分支。如果RM判断自己进行的工作可以被提交,那就对工作内容进行持久化,再给TM肯定答复;要是发生了其他情况,那给TM的都是否定答复。

阶段2

TM根据阶段1各个RM prepare的结果,决定是提交还是回滚事务。如果所有的RM都prepare成功,那么TM通知所有的RM进行提交;如果有RM prepare失败的话,则TM通知所有RM回滚自己的事务分支。

两阶段提交方案下全局事务的ACID特性,是依赖于RM的。一个全局事务内部包含了多个独立的事务分支,这一组事务分支要么都成功,要么都失败。各个事务分支的ACID特性共同构成了全局事务的ACID特性。也就是将单个事务分支支持的ACID特性提升一个层次到分布式事务的范畴。

2PC存在的问题

  • 同步阻塞问题

2PC 中的参与者是阻塞的。在第一阶段收到请求后就会预先锁定资源,一直到 commit 后才会释放。

  • 单点故障

由于协调者的重要性,一旦协调者TM发生故障,参与者RM会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。

  • 数据不一致

若协调者第二阶段发送提交请求时崩溃,可能部分参与者收到commit请求提交了事务,而另一部分参与者未收到commit请求而放弃事务,从而造成数据不一致的问题。

Seata

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS(Global Transaction Service 全局事务服务)

Seata的三大角色

在 Seata 的架构中,一共有三个角色:

  • TC (Transaction Coordinator) - 事务协调者

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

  • TM (Transaction Manager) - 事务管理器

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

  • RM (Resource Manager) - 资源管理器

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

其中,TC 为单独部署的 Server 服务端,TM 和 RM 为嵌入到应用中的 Client 客户端。

Seata的生命周期

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

  1. TM 请求 TC 开启一个全局事务。TC 会生成一个 XID 作为该全局事务的编号。XID会在微服务的调用链路中传播,保证将多个微服务的子事务关联在一起。
  2. RM 请求 TC 将本地事务注册为全局事务的分支事务,通过全局事务的 XID 进行关联。
  3. TM 请求 TC 告诉 XID 对应的全局事务是进行提交还是回滚。
  4. TC 驱动 RM 们将 XID 对应的自己的本地事务进行提交还是回滚。

Seata解决方案

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

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

AT模式

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

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

  • 二阶段:

    • 提交异步化,非常快速地完成。

    • 回滚通过一阶段的回滚日志进行反向补偿。

一阶段

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

二阶段
  • 分布式事务操作成功,则TC通知RM异步删除undolog
  • 分布式事务操作失败,TM向TC发送回滚请求,RM 收到协调器TC发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。

XA模式

XA协议最主要的作用是就是定义了RM-TM的交互接口,XA规范除了定义的RM-TM交互的接口(XA Interface)之外,还对两阶段提交协议进行了优化。

在 Seata 定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种 事务模式。

  • 执行阶段:

    • 可回滚:业务 SQL 操作放在 XA 分支中进行,由资源对 XA 协议的支持来保证 可回滚

    • 持久化:XA 分支完成后,执行 XA prepare,同样,由资源对 XA 协议的支持来保证 持久化

  • 完成阶段:

    • 分支提交:执行 XA 分支的 commit

    • 分支回滚:执行 XA 分支的 rollback

TCC模式

TCC 基于分布式事务中的二阶段提交协议实现,它的全称为 Try-Confirm-Cancel,即资源预留(Try)、确认操作(Confirm)、取消操作(Cancel),他们的具体含义如下:

  1. Try:对业务资源的检查并预留;
  2. Confirm:对业务处理进行提交,即 commit 操作,只要 Try 成功,那么该步骤一定成功;
  3. Cancel:对业务处理进行取消,即回滚操作,该步骤回对 Try 预留的资源进行释放。
  • XA是资源层面的分布式事务,强一致性,在两阶段提交的整个过程中,一直会持有资源的锁。

  • TCC是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。

TCC 是一种侵入式的分布式事务解决方案,以上三个操作都需要业务系统自行实现,对业务系统有着非常大的入侵性,设计相对复杂,但优点是 TCC 完全不依赖数据库,能够实现跨数据库、跨应用资源管理,对这些不同数据访问通过侵入式的编码方式实现一个原子操作,更好地解决了在各种复杂业务场景下的分布式事务问题。

一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:

  • 一阶段 prepare 行为

  • 二阶段 commit 或 rollback 行为

在Seata中,AT模式与TCC模式事实上都是两阶段提交的具体实现,他们的区别在于:

AT 模式基于 支持本地 ACID 事务的关系型数据库:

  • 一阶段 prepare 行为:在本地事务中,一并提交业务数据更新和相应回滚日志记录。

  • 二阶段 commit 行为:马上成功结束,自动异步批量清理回滚日志。

  • 二阶段 rollback 行为:通过回滚日志,自动生成补偿操作,完成数据回滚。

相应的,TCC 模式不依赖于底层数据资源的事务支持:

  • 一阶段 prepare 行为:调用自定义的 prepare 逻辑。

  • 二阶段 commit 行为:调用自定义的 commit 逻辑。

  • 二阶段 rollback 行为:调用自定义的 rollback 逻辑。

简单点概括,SEATA的TCC模式就是手工的AT模式,它允许你自定义两阶段的处理逻辑而不依赖AT模式的undo_log。

在 TCC 模型执行的过程中,还可能会出现各种异常,其中最为常见的有空回滚、幂等、悬挂等。TCC 模式是分布式事务中非常重要的事务模式,但是幂等、悬挂和空回滚一直是 TCC 模式需要考虑的问题,Seata 框架在 1.5.1 版本完美解决了这些问题。

如何处理空回滚

空回滚指的是在一个分布式事务中,在没有调用参与方的 Try 方法的情况下,TM 驱动二阶段回滚调用了参与方的 Cancel 方法。

要想防止空回滚,那么必须在 Cancel 方法中识别这是一个空回滚,Seata 是如何做的呢?

Seata 的做法是新增一个 TCC 事务控制表,包含事务的 XID 和 BranchID 信息,在 Try 方法执行时插入一条记录,表示一阶段执行了,执行 Cancel 方法时读取这条记录,如果记录不存在,说明 Try 方法没有执行。

如何处理幂等

幂等问题指的是 TC 重复进行二阶段提交,因此 Confirm/Cancel 接口需要支持幂等处理,即不会产生资源重复提交或者重复释放。

Seata 是如何处理幂等问题的呢?

同样的也是在 TCC 事务控制表中增加一个记录状态的字段 status,该字段有 3 个值,分别为:

  1. tried:1
  2. committed:2
  3. rollbacked:3

二阶段 Confirm/Cancel 方法执行后,将状态改为 committed 或 rollbacked 状态。当重复调用二阶段 Confirm/Cancel 方法时,判断事务状态即可解决幂等问题。

如何处理悬挂

悬挂指的是二阶段 Cancel 方法比 一阶段 Try 方法优先执行,由于允许空回滚的原因,在执行完二阶段 Cancel 方法之后直接空回滚返回成功,此时全局事务已结束,但是由于 Try 方法随后执行,这就会造成一阶段 Try 方法预留的资源永远无法提交和释放了。

Seata 是怎么处理悬挂的呢?

在 TCC 事务控制表记录状态的字段 status 中增加一个状态:

  • suspended:4

当执行二阶段 Cancel 方法时,如果发现 TCC 事务控制表没有相关记录,说明二阶段 Cancel 方法优先一阶段 Try 方法执行,因此插入一条 status=4 状态的记录,当一阶段 Try 方法后面执行时,判断 status=4 ,则说明有二阶段 Cancel 已执行,并返回 false 以阻止一阶段 Try 方法执行成功。

SAGA模式

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

  • 一阶段:直接提交本地事务(TCC是预留)
  • 二阶段:成功则什么都不做;失败则通过编写补偿业务来回滚

Saga模式优点:

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

缺点:

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

四种模式对比

- XA AT TCC SAGA
一致性 强一致 弱一致 弱一致 最终一致
隔离性 完全隔离 基于全局锁隔离 基于资源预留隔离 无隔离
代码侵入 有,需要编写3个接口 有,需要编写状态机和补偿业务
性能 非常好 非常好
场景 对一致性、隔离性有高要求的业务 基于关系型数据库的大多数分布式事务场景都可以 对性能要求较高的事务;有非关系型数据库要参与的事务 业务流程长、业务流程多;参与者包含其它公司或遗留系统服务,无法提供TCC模式要求的三个接口
相关推荐
傻啦嘿哟1 分钟前
Python多线程与类方法的交互:锁提升安全性的奥秘
java·开发语言
半盏茶香2 分钟前
启航数据结构算法之雅舟,悠游C++智慧之旅——线性艺术:顺序表之细腻探索
c语言·开发语言·数据结构·c++·算法·机器学习·链表
已是上好佳13 分钟前
java实验4 反射机制
java·开发语言
小园子的小菜18 分钟前
Rockect基于Dledger的Broker主从同步原理
java·开发语言
鹿屿二向箔20 分钟前
【论文+源码】创建一个基于Spring Boot的体育场管理系统
java·spring boot·后端
漫无目的行走的月亮20 分钟前
Spring boot实现图片上传和下载
java·spring boot
火云牌神32 分钟前
[python]实现可以自动清除过期条目的缓存
开发语言·python·缓存
Libby博仙34 分钟前
asp.net core Web Api中的数据绑定
java·前端·asp.net
小金的学习笔记40 分钟前
SpringBootWeb案例-2
java·服务器·springboot·web
杰九43 分钟前
【全栈】SprintBoot+vue3迷你商城(2)
java·数据库·spring boot·mysql