从零开始学Seata:分布式事务的终极解决方案

news/2025/3/22 15:17:13/
一、什么是Seata?—— 分布式事务的“全自动管家”

Seata 是一款开源的分布式事务框架,旨在解决微服务架构下的数据一致性问题。其核心目标是**“让开发者专注业务,自动管理事务”**,通过 AT模式(Automatic Transaction)TCC模式Saga模式 等多种协议实现强一致性和最终一致性。

核心角色
TC(Transaction Coordinator):事务协调者,统筹全局事务(类似裁判)。
TM(Transaction Manager):事务管理器,定义事务边界(类似教练)。
RM(Resource Manager):资源管理器,管理数据库连接等资源(类似球员)。

通俗比喻
想象你带领一支足球队(分布式服务),Seata 就是你的战术板:
TC:负责指挥全场(协调所有服务)。
TM:制定比赛策略(定义事务范围)。
RM:执行具体动作(扣库存、扣款等)。


二、Seata原理:一键式事务管理
1. AT模式(核心模式)

核心思想
自动记录Undo Log:在业务代码执行前后自动记录操作日志。
提交即提交,回滚即恢复:通过异步任务回滚失败事务。
流程图解

TM → TC:注册事务  
RM → TC:报告分支状态  
TC → 所有RM:提交/回滚  
RM → 自动执行Undo Log回滚  
2. TCC模式

核心思想
三阶段手动控制
1. Try:尝试执行业务(扣库存)。
2. Confirm:确认成功后提交。
3. Cancel:失败时触发补偿(恢复库存)。
适用场景:需要精细控制补偿逻辑的长事务。

3. Saga模式

核心思想
事件驱动补偿:通过事件触发正向操作和逆向补偿。
最终一致性:允许短暂不一致,但最终状态一致。


三、Seata适用场景

以下场景强烈推荐使用Seata:

  1. 电商订单:扣减库存 → 生成订单 → 扣款 → 发货,任一环节失败需全盘回滚。
  2. 金融转账:A账户扣款 → B账户加款,必须强一致性。
  3. 微服务解耦:订单服务、支付服务、物流服务独立部署,需事务协同。
  4. 高并发场景:秒杀活动(需通过Seata避免超卖)。

反例
日志记录:允许异步写入,无需事务。
统计报表:数据允许延迟几分钟。


四、实战:Spring Boot + Seata 快速上手
1. 环境准备

下载Seata Server:访问 官网 下载最新版(以2.1.0为例)。
启动服务

# 启动TC(协调者)
sh seata-server.bat -p 8091 -h 127.0.0.1# 启动TM(事务管理器)和RM(资源管理器)
sh seata-server.bat -p 8092 -h 127.0.0.1
2. Spring Boot项目集成
2.1 添加依赖

pom.xml 中添加Seata和MySQL驱动:

<dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>2.1.0</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
</dependency>
2.2 配置数据源代理

application.yml 中配置Seata数据源:

spring:datasource:url: jdbc:mysql://localhost:3306/seata_db?useSSL=false&serverTimezone=UTCusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid:max-active: 20seata:tx-service-group: my_test_tx_groupenable-auto-commit: falseservice-component:tx-manager:service-name: seata-tm-serviceregister-center:type: nacosnacos:server-addr: 127.0.0.1:8848tx-coordinator:service-name: seata-tc-serviceregister-center:type: nacosnacos:server-addr: 127.0.0.1:8848
2.3 业务代码实现
2.3.1 订单服务(TM)
@Service
public class OrderService {@Autowiredprivate InventoryService inventoryService;@Autowiredprivate PaymentService paymentService;@GlobalTransactional(timeout=30000, name="createOrder", rollbackFor=Exception.class)public void createOrder(Order order) {// 1. 扣减库存inventoryService.deduct(order.getSkuId());// 2. 扣款paymentService.charge(order.getUserId(), order.getAmount());// 3. 生成订单orderDAO.insert(order);}
}
2.3.2 库存服务(RM)
@Service
public class InventoryService {@Autowiredprivate InventoryDAO inventoryDAO;@Transactionalpublic void deduct(String sku) {Inventory inventory = inventoryDAO.findBySku(sku);if (inventory.getStock() <= 0) {throw new RuntimeException("库存不足,SKU: " + sku);}inventory.setStock(inventory.getStock() - 1);inventoryDAO.update(inventory);}
}
2.3.3 支付服务(RM)
@Service
public class PaymentService {@Autowiredprivate PaymentDAO paymentDAO;@Transactionalpublic void charge(String userId, BigDecimal amount) {Payment payment = paymentDAO.findByUserId(userId);if (payment == null) {throw new RuntimeException("用户未找到,ID: " + userId);}payment.setBalance(payment.getBalance().subtract(amount));paymentDAO.update(payment);}
}

3. 测试与验证
3.1 正常流程

发送请求创建订单:

Order order = new Order();
order.setUserId("user123");
order.setAmount(new BigDecimal("100.00"));
order.setSkuId("SKU_123");
orderService.createOrder(order);

预期结果
• 库存扣减成功。
• 支款成功。
• 订单生成。

3.2 模拟支付失败

PaymentService.charge 中抛出异常:

public void charge(String userId, BigDecimal amount) {throw new RuntimeException("支付失败!");
}

预期结果
• 库存自动恢复。
• 订单状态回滚。
• 支款操作撤销。


4. 关键原理与优势
1. AT模式的核心流程

Branch Registration:TM向TC注册分支事务。
Local Transaction:各RM执行本地事务并记录Undo Log。
Commit/Rollback:TC汇总结果,提交或触发异步回滚。

2. 优势对比传统2PC

无代码侵入:通过 @GlobalTransactional 注解自动管理事务。
高性能:基于乐观锁和异步回滚,减少资源阻塞。
高可用:TC集群化部署,避免单点故障。


五、常见问题与解决
1. 事务未提交/回滚

检查点
• 确保 @GlobalTransactional 注解标注在 TM 方法上。
• 确认Seata Server和Nacos服务正常运行。

2. 数据不一致

解决方案
• 检查 undo_log 表是否正常记录回滚信息。
• 验证本地事务的 @Transactional 是否生效。

3. 超时问题

调整配置
• 在 application.yml 中设置 global.tx.timeout=30000(默认30秒)。
• 优化业务逻辑,减少事务执行时间。

4. 服务调用失败

解决方案
• 结合重试机制(如Resilience4j)自动重试。
• 在 @GlobalTransactional 中配置 rollbackFor 异常类型。


六、总结与行动建议
  1. 掌握基础:通过示例代码理解Seata的AT模式和注解机制。
  2. 使用框架:生产环境推荐Seata,避免手动实现2PC/TCC/Saga。
  3. 避坑指南
    集群化部署:TC和TM/RM部署在多个节点。
    监控日志:通过Seata控制台查看事务状态。
    超时设置:根据业务需求合理配置超时时间。
  4. 进阶方向
    • 结合Saga模式处理复杂补偿逻辑。
    • 通过Seata Studio可视化监控事务链路。

最后思考
Seata是分布式事务的“瑞士军刀”,既能通过AT模式实现强一致性,又支持TCC/Saga灵活应对不同场景。对于大多数互联网项目,尤其是金融和电商领域,Seata是值得优先选择的解决方案。入门虽难,但通过官方文档和社区资源,可以快速上手并落地。


http://www.ppmy.cn/news/1581164.html

相关文章

威联通 后台可用命令查看Bash

一、查看所有可用命令的方法 列出所有外部命令&#xff08;二进制文件&#xff09; 外部命令通常存放在系统路径&#xff08;如 /bin, /usr/bin, /sbin, /usr/sbin&#xff09;中&#xff1a; bash ls /bin /usr/bin /sbin /usr/sbin # 直接列出命令目录&#xff08;结果较长&…

Jenkins 容器化部署 uniapp H5 项目

jenkins 容器化部署 uniapp H5 项目 背景 Linux 上使用 uniapp-cli不顺利windows server 服务器安装 Docker 环境不顺利 思路 在 Windows 机器上安装 HBuilder调用 uniapp-cli 打包 H5 文件将输出文件发送到 有 Docker 环境的服务器上打包 Docker 镜像推送镜像到镜像仓库 …

前端网络请求

为什么需要做网络请求&#xff1f; 例如哔哩哔哩官网上展现的资源其实都是通过请求获取的&#xff1a; 是从霹雳霹雳服务器上请求信息&#xff0c;然后传输到客户端本地&#xff08;浏览器&#xff09; 页面资源越多&#xff0c;传输的的次数越多&#xff0c;每一次的传输就被…

第P8周:YOLOv5-C3模块实现

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 &#x1f3e1; 我的环境&#xff1a; ● 语言环境&#xff1a;Python3.8 ● 编译器&#xff1a;Jupyter Lab ● 数据集&#xff1a;天气识别数据集 ● 深度学…

【C++基础】Lambda 函数 基础知识讲解学习及难点解析

一、引入 在 C 中&#xff0c;我们通常使用函数来完成特定的功能。但有时候&#xff0c;我们需要在一个函数内部定义一个小型的功能块&#xff0c;这时如果单独写一个函数会显得繁琐。C11 引入了 Lambda 函数&#xff0c;它是一种匿名函数&#xff0c;可以在需要的地方直接定义…

doris:负载均衡

用户通过 FE 的查询端口&#xff08;query_port&#xff0c;默认 9030&#xff09;使用 MySQL 协议连接 Doris。当部署多个 FE 节点时&#xff0c;用户可以在多个 FE 之上部署负载均衡层来实现 Doris 查询的高可用。 本文档介绍多种适用于 Doris 的负载均衡方案&#xff0c;并…

XSS 绕过分析:一次循环与两次循环的区别

目录 代码分析 代码流程&#xff1a; 一次循环的问题 原因分析&#xff1a;删除顺序导致遗漏 两次循环修复方案 两种绕过方式 绕过方法 1&#xff1a;DOM破环 绕过方法 2&#xff1a;SVG XSS&#xff08;双 SVG 绕过&#xff09; 1. 为什么 "一个SVG注定失败&…

[特殊字符] 2025蓝桥杯备赛Day8——B2118 验证子串

&#x1f50d; 2025蓝桥杯备赛Day8——B2118 验证子串 &#x1f680; 题目速览 题目难度&#xff1a;⭐️ 适合掌握字符串基本操作 考察重点&#xff1a;子串判断、字符串查找、条件分支处理 B2118 验证子串 题目描述 输入两个字符串&#xff0c;验证其中一个串是否为另一…