分布式事务Seata详解

文章目录

    • 简介
    • 四种模式的优劣势:
    • 实现原理
    • demo

简介

Seata是一款开源的分布式事务解决方案,提供了全局事务管理和协调服务,支持多种主流的数据库和RPC框架,以及Spring Cloud和Dubbo等微服务框架。Seata的设计目标是解决分布式事务的一致性问题,实现高可用、高性能、易扩展的分布式事务管理。
Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata有四种模式,分别是AT、TCC、Saga和XA。
AT模式:用户只需关心自己的“业务SQL”。在AT模式下,一阶段,Seata会拦截“业务 SQL”,首先解析 SQL 语义,找到“业务 SQL”要更新的业务数据,在业务数据被更新前,将其保存成“before image”,然后执行“业务 SQL”更新业务数据,在业务数据更新之后,再将其保存成“after image”,最后生成行锁。以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
TCC模式:Try(执行业务)、Confirm(确认)和 Cancel(撤销)是它的核心思想。它需要在业务代码中明确的进行两个阶段(Try/Confirm)操作。
Saga模式:Saga模式是一种长事务模式,它将一个长事务拆分成多个小事务,每个小事务都是一个短事务。Saga模式的核心思想是补偿,即如果某个小事务失败了,可以通过回滚之前的小事务来保证整个长事务的正确性。
XA模式:XA模式是一种全局事务模式,它可以将一个分布式事务拆分成多个本地事务,并在全局事务管理器(Transaction Manager)的控制下协同完成。XA模式适用于高并发、跨多个服务或数据库的全局事务场景。

Seata 是用来解决分布式事务问题的框架。是阿里开源的中间件。
Seata 中封装了四种分布式事务模式,分别是:
AT 模式,是一种基于本地事务+二阶段协议来实现的最终数据一致性方案,也是Seata 默认的解决方案
TCC 模式,TCC 事务是 Try、Confirm、Cancel 三个词语的缩写,简单理解就是把一个完整的业务逻辑拆分成三个阶段,然后通过事务管理器在业务逻辑层面
Saga 模式,Saga 模式是 SEATA 提供的长事务解决方案,在 Saga 模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者。
XA 模式,XA 可以认为是一种强一致性的事务解决方法,它利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种事务模式。
从这四种模型中不难看出,在不同的业务场景中,我们可以使用 Seata 的不同
事务模型来解决不同业务场景中的分布式事务问题,因此我们可以认为 Seata是一个一站式的分布式事务解决方案。

Seata有三个组成部分:事务协调器TC:协调者、事务管理器TM:发起方、资源管理器RM:参与方
(1)发起方会向协调者申请一个全局事务id,并保存到ThreadLocal中(为什么要保存到ThreadLocal中?弱引用,线程之间不会发生数据冲突)
(2)Seata数据源代理发起方和参与方的数据源,将前置镜像和后置镜像写入到undo_log表中,方便后期回滚使用
(3)发起方获取全局事务id,通过改写Feign客户端请求头传入全局事务id。
(4)参与方从请求头中获取全局事务id保存到ThreadLocal中,并把该分支注册到SeataServer中。
(5)如果没有出现异常,发起方会通知协调者,协调者通知所有分支,通过全局事务id和本地事务id删除undo_log数据,如果出现异常,通过undo_log逆向生成sql语句并执行,然后删除undo_log语句。如果处理业务逻辑代码超时,也会回滚。

四种模式的优劣势:

AT 模式(自动补偿型事务):
○ 原理:在事务参与方中嵌入逆向SQL语句进行补偿。
○ 优点:简化了编程模型,对业务代码无侵入性,可以在不修改业务逻辑的情况下实现分布式事务。
○ 缺点:需要在业务逻辑中手动编写逆向SQL语句,一定程度上增加了开发和维护的成本。对于长事务或高并发场景,可能会有较大的性能开销。
TCC 模式(两阶段型事务):
○ 原理:将分布式事务拆分为Try、Confirm和Cancel三个阶段,并提供相应的接口实现来实现分布式事务的一致性。
○ 优点:具备较好的可靠性和灵活性,可以在不同阶段执行自定义的业务逻辑。
○ 缺点:需要在业务逻辑中显式地编写Try、Confirm和Cancel操作,并保证幂等性。对于业务复杂的场景,编写和维护TCC接口可能比较繁琐。
Saga 模式(补偿型事务):
○ 原理:通过定义状态机来实现分布式事务的一致性,事务执行过程中可能会有多次补偿操作。
○ 优点:适用于复杂的业务场景,可以在不同的阶段执行自定义的补偿操作,并具备较好的可靠性。
○ 缺点:对于长事务,可能需要执行多次补偿操作,可能会增加系统的复杂性和开销。
XA 模式(两阶段提交):
○ 原理:使用XA协议实现分布式事务的一致性,通过协调器来协调各个事务参与方的提交或回滚。
○ 优点:XA是一种标准化的分布式事务协议,具备较高的可靠性,并且在一些数据库和应用服务器中已经内置了XA支持。
○ 缺点:XA模式在性能和扩展性方面可能存在一些瓶颈,而且对数据库和应用的支持要求较高。
需要根据具体的业务需求、性能要求和开发维护成本来选择合适的分布式事务模式。不同模式适用于不同的场景,选择合适的模式可以提高分布式事务的性能和可靠性。

实现原理

Seata是一款开源的分布式事务解决方案,其实现原理主要涉及全局事务管理和协调服务,以及对多种数据库和RPC框架的支持。以下是Seata实现原理的简要概述:
undefined 全局事务管理:
○ Seata通过一个全局事务管理器(Transaction Coordinator)来协调和管理分布式事务的整个过程。全局事务管理器负责发起和提交全局事务,并与各个事务参与方进行通信和协调。
undefined 事务参与方:
○ 在分布式事务中,各个数据库、消息队列或远程服务等被称为事务参与方。Seata通过对这些事务参与方进行代理和增强,以实现全局事务的一致性。
undefined 事务日志存储:
○ Seata会将全局事务的相关信息和操作记录进行持久化存储,以保证全局事务在发生故障或恢复时能够正确地进行恢复和处理。
undefined 并发控制:
○ Seata通过并发控制机制来保证分布式事务的一致性和隔离性,包括锁机制、版本控制等方式来避免并发冲突。
undefined 事务补偿:
○ 对于AT模式和Saga模式,Seata会通过事务补偿机制来实现分布式事务的一致性。当某个参与方出现异常时,Seata可以根据事务日志中的记录执行逆向操作或者补偿操作,以确保全局事务的一致性。
总体来说,Seata通过全局事务管理器、事务参与方、事务日志存储、并发控制和事务补偿等机制,实现了对分布式事务的统一管理和协调,从而保证了分布式系统中的事务一致性和可靠性。同时,Seata支持的多种模式和灵活的配置选项,使得它能够适应不同的业务场景和需求。

demo

Seata的代码实现包括以下几个方面:

  1. 环境依赖和配置:
    ○ 在项目的pom.xml文件中添加Seata的相关依赖,例如seata-all、seata-spring-boot-starter等。
    ○ 在项目的配置文件(如application.properties或application.yml)中配置Seata的相关参数,如服务端地址、事务分组、数据源代理等。
  2. 事务发起方的代码实现:
    ○ 在需要进行分布式事务管理的方法上添加@GlobalTransactional注解。
    ○ 使用Seata提供的TransactionContext对象来处理分支事务,如创建分支事务、提交或回滚分支事务。示例代码如下:
import io.seata.spring.annotation.GlobalTransactional;
import io.seata.core.context.RootContext;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @GlobalTransactional
    public void createOrder(OrderDTO orderDTO) {
        // 1. 开启全局事务
        String xid = RootContext.getXID();

        try {
            // 2. 创建订单
            Order order = new Order();
            // 设置订单信息

            orderMapper.insert(order);

            // 3. 创建其它业务数据
            // ...

            // 4. 提交分支事务
            // 这里可以不用显式调用,Seata会在方法执行结束后自动提交分支事务
        } catch (Exception e) {
            // 5. 回滚分支事务
            // 这里可以不用显式调用,Seata会根据全局事务的状态自动回滚分支事务
        }
    }
}

3. 事务参与方的代码实现: 
  ○ 在事务参与方的数据库访问、消息发送或远程调用等操作前,使用Seata提供的@GlobalTransactional注解开启分支事务。
  ○ 在方法执行结束后,Seata会根据全局事务的状态自动提交或回滚分支事务。示例代码如下:

import io.seata.spring.annotation.GlobalTransactional;
import io.seata.core.context.RootContext;

@Service
public class InventoryService {

    @GlobalTransactional
    public void reduceStock(String productId, int quantity) {
        String xid = RootContext.getXID();

        try {
            // 1. 扣减库存
            // ...

            // 2. 提交分支事务
            // 这里可以不用显式调用,Seata会在方法执行结束后自动提交分支事务
        } catch (Exception e) {
            // 3. 回滚分支事务
            // 这里可以不用显式调用,Seata会根据全局事务的状态自动回滚分支事务
        }
    }
}

以上是Seata的基本代码实现示例。在实际应用中,需要根据业务场景和具体需求进行适当的调整和扩展。另外,Seata还提供了更多高级特性和灵活的配置选项,可以根据需要进行深入学习和使用。

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