04-Seata 深度解析:从分布式事务原理到 Seata 实战落地

打印 上一主题 下一主题

主题 1617|帖子 1617|积分 4851

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Seata 深度解析:从分布式事务原理到 Seata 实战落地

一、分布式事务核心理论与寻衅

1.1 分布式事务的本质困难

在微服务架构中,一次业务操作可能涉及多个服务的数据库操作,传统单体事务(ACID)无法凌驾服务边界,导致以下核心标题:


  • 原子性粉碎:跨服务操作部分成功、部分失败时如何回滚?
  • 同等性缺失:分布式环境下如何保证数据最终同等?
  • 网络分区影响:节点间通信失败时如何处理事务状态?
1.2 分布式事务模型对比

模型核心头脑典型方案同等性级别性能特点实用场景强同等全局锁 / 两阶段提交(2PC)XA 协议、Seata TC 模式强同等低并发(锁粒度大)金融转账、订单支付最终同等赔偿机制(TCC/SAGA)、可靠消息Seata AT/TCC/SAGA 模式最终同等高并发(无全局锁)电商库存扣减、物流同步最大努力重试 + 人工干预事务消息 + 本地消息表最终同等高可用(允许重试)非核心业务流程 二、Seata 架构与核心组件解析

2.1 Seata 团体架构

     2.2 核心组件功能


  • TC(事务和谐者)

    • 维护全局事务状态(初始化、提交、回滚)
    • 和谐各服务 RM 完身分支事务的提交 / 回滚
    • 支持 Nacos/Redis/MySQL 作为事务日志存储

  • TM(事务管理器)

    • 发起全局事务(@GlobalTransactional 注解驱动)
    • 控制全局事务的提交 / 回滚机遇

  • RM(资源管理器)

    • 管理本地数据库连接(通过数据源代理实现)
    • 记录 UNDO 日志(用于 AT 模式主动赔偿)
    • 响应 TC 指令完身分支事务的提交 / 回滚

2.3 三大事务模式对比

(1)AT 模式(主动赔偿)



  • 核心原理:

    • 执行前记录数据快照(UNDO 日志)
    • 执行业务 SQL 并提交本地事务
    • 全局事务提交时直接确认,回滚时根据 UNDO 日志反向赔偿

  • 优点:无侵入性(只需添加 Seata 依赖),适配现有业务代码
  • 缺点:需创建undo_log表,高并发下存在锁竞争
(2)TCC 模式(两阶段提交)



  • 核心原理:

    • Try:预留资源(如冻结库存)
    • Confirm:正式提交资源(扣减库存)
    • Cancel:释放预留资源(解冻库存)

  • 优点:细粒度资源控制,得当跨服务复杂逻辑
  • 缺点:需手动实现三个阶段,开辟本钱高
(3)SAGA 模式(长事务赔偿)



  • 核心原理:

    • 将长事务拆分为多个本地事务,每个事务附带反向赔偿逻辑
    • 当某一步失败时,按相反顺序执行赔偿事务

  • 优点:无全局锁,得当异步、最终同等场景
  • 缺点:赔偿逻辑需自行实现,事务链路长时状态管理复杂
三、Seata AT 模式实战:订单 - 库存分布式事务

3.1 环境预备



  • 技能栈:Spring Boot 3.1.2 + Seata 1.6.1 + Nacos 2.3.1
  • 场景:用户下单时扣减库存,确保订单与库存操作要么全成功、要么全回滚
3.2 核心配置步骤

(1)TC 服务摆设(Seata Server)

  1. # 下载Seata Server  
  2. wget https://github.com/seata/seata/releases/download/v1.6.1/seata-server-1.6.1.tar.gz  
  3. # 修改registry.conf使用Nacos  
  4. registry {  
  5.   type = "nacos"  
  6.   serverAddr = "nacos:8848"  
  7.   namespace = ""  
  8. }  
  9. # 启动TC服务  
  10. sh seata-server.sh -m file  
复制代码
(2)业务服务集成 Seata


  • 添加依赖:
    1. <dependency>  
    2.     <groupId>com.alibaba.cloud</groupId>  
    3.     <artifactId>spring-cloud-starter-alibaba-seata</artifactId>  
    4. </dependency>  
    复制代码
  • 配置application.yml:
    1. seata:  
    2.   tx-service-group: my_test_tx_group  # 事务分组名称  
    3.   service:  
    4.     vgroup-mapping:  
    5.       my_test_tx_group: default  # 映射到Seata Server的default分组  
    复制代码
(3)创建 UNDO 日志表

  1. CREATE TABLE `undo_log` (  
  2.   `id` bigint(20) NOT NULL AUTO_INCREMENT,  
  3.   `branch_id` bigint(20) NOT NULL,  
  4.   `xid` varchar(100) NOT NULL,  
  5.   `context` varchar(128) NOT NULL,  
  6.   `rollback_info` longblob NOT NULL,  
  7.   `log_status` int(11) NOT NULL,  
  8.   `log_created` datetime NOT NULL,  
  9.   `log_modified` datetime NOT NULL,  
  10.   PRIMARY KEY (`id`),  
  11.   UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)  
  12. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;  
复制代码
3.3 代码实现

(1)订单服务(发起全局事务)

  1. @Service  
  2. public class OrderService {  
  3.     @GlobalTransactional(name = "createOrder", rollbackFor = Exception.class)  
  4.     public void createOrder(Order order) {  
  5.         // 1. 保存订单  
  6.         orderRepository.save(order);  
  7.         // 2. 调用库存服务扣减库存  
  8.         stockFeignClient.deductStock(order.getProductId(), order.getQuantity());  
  9.     }  
  10. }  
复制代码
(2)库存服务(分支事务)

  1. @Service  
  2. public class StockService {  
  3.     public void deductStock(Long productId, Integer quantity) {  
  4.         Stock stock = stockRepository.findByProductId(productId);  
  5.         if (stock.getStock() < quantity) {  
  6.             throw new RuntimeException("库存不足");  
  7.         }  
  8.         stock.setStock(stock.getStock() - quantity);  
  9.         stockRepository.save(stock);  
  10.     }  
  11. }  
复制代码
3.4 异常处理与回滚验证



  • 正常提交:订单与库存操作均成功,全局事务提交
  • 库存不足回滚:库存服务抛异常,Seata 主动回滚订单插入操作
  • 查看 UNDO 日志:回滚时根据undo_log表规复订单表数据
四、生产环境最佳实践

4.1 性能优化战略

(1)UNDO 日志优化



  • 批量删除过期日志:定期清理undo_log表中状态为已回滚或已提交的记录
  • 分库分表:按xid或branch_id哈希分表,制止单表数据量过大
(2)事务分组设计



  • 按业务场景分别事务分组(如order_tx_group、payment_tx_group)
  • 差别分组对应差别的 Seata Server 集群,制止跨业务事务干扰
(3)锁优化



  • 启用globalTable全局锁表(Seata 1.5 + 新增),办理多服务操作同一资源时的脏写标题
  • 调解seata.tm.lock.wait-timeout(默认 30 秒)制止长时锁等候
4.2 高可用架构设计

(1)TC 集群摆设

  1. # Nacos配置中心存储Seata集群信息  
  2. seata:  
  3.   registry:  
  4.     type: nacos  
  5.     server-addr: nacos-cluster:8848  
  6.   config:  
  7.     type: nacos  
  8.     server-addr: nacos-cluster:8848  
  9.     namespace: seata-config  
复制代码
(2)RM 数据源代理



  • 利用SeataDataSourceProxy代理数据源,支持 XA 模式与 AT 模式切换
  • 配置连接池参数(如 HikariCP 的connectionTimeout=30000)制止超时
4.3 监控与故障排查

(1)核心监控指标



  • seata_tm_commit_success:全局事务提交成功数
  • seata_tm_rollback_count:全局事务回滚数
  • seata_rm_undo_log_size:UNDO 日志表数据量
(2)排查工具



  • Seata Dashboard:可视化查看全局事务状态、分支事务详情
  • 日志分析:

    • TC 日志定位事务和谐失败缘故原由(io.seata.server.log)
    • RM 日志查看 UNDO 日志生成与赔偿过程(io.seata.rm.datasource)

五、分布式事务方案选型指南

5.1 技能选型决议树

     5.2 各方案对比总结

方案开辟本钱性能同等性实用场景Seata AT低中高最终同等简单 CRUD 场景(如订单、库存)Seata TCC高高最终同等复杂业务逻辑(如跨服务资源预留)Seata SAGA中高最高最终同等长事务流程(如物流状态机)XA 协议低低强同等金融级强同等场景(如账户转账) 六、Seata 源码深度解析:AT 模式核心流程

6.1 全局事务开启

  1. // TransactionalTemplate.java  
  2. public Object execute(TransactionTemplate.TransactionCallback action) {  
  3.     // 1. 生成XID(全局事务ID)  
  4.     String xid = transactionManager.begin();  
  5.     try {  
  6.         // 2. 执行业务逻辑  
  7.         Object result = action.doInTransaction();  
  8.         // 3. 提交全局事务  
  9.         transactionManager.commit(xid);  
  10.         return result;  
  11.     } catch (Exception e) {  
  12.         // 4. 回滚全局事务  
  13.         transactionManager.rollback(xid);  
  14.         throw e;  
  15.     }  
  16. }  
复制代码
6.2 分支事务注册

  1. // AbstractDataSourceProxy.java  
  2. public Connection getConnection() throws SQLException {  
  3.     Connection conn = physicalConnection;  
  4.     // 注册分支事务(绑定XID)  
  5.     RootContext.bind(xid);  
  6.     return new ConnectionProxy(conn, this);  
  7. }  
复制代码
6.3 UNDO 日志生成

  1. // UndoLogManager.java  
  2. public void generateUndoLog(Connection conn, String xid, long branchId, SQLRecognizer sqlRecognizer) {  
  3.     // 1. 解析SQL获取表名、主键  
  4.     String tableName = sqlRecognizer.getTableName();  
  5.     Object pk = sqlRecognizer.getPrimaryKey();  
  6.     // 2. 查询旧数据快照  
  7.     String oldRow = queryOldData(conn, tableName, pk);  
  8.     // 3. 记录UNDO日志  
  9.     insertUndoLog(conn, xid, branchId, tableName, oldRow, newRow);  
  10. }  
复制代码
七、总结与未来方向

7.1 Seata 核心代价



  • 无侵入性:AT 模式只需添加依赖,无需修改现有业务代码
  • 多模式支持:一套框架覆盖强同等与最终同等场景
  • 生态整合:与 Nacos、Sentinel、Spring Cloud 深度集成
7.2 寻衅与应对



  • 性能消耗:AT 模式的 UNDO 日志与全局锁会带来 10%-20% 的性能开销,需通过连接池优化、批量操作镌汰影响
  • 异常处理:赔偿逻辑需考虑幂等性(如通过xid+branch_id唯一键制止重复赔偿)
7.3 未来趋势


  • Serverless 支持:轻量化 Seata TC 摆设,适配 Knative 等 Serverless 架构
  • 多云协同:跨云厂商的分布式事务办理方案(如 Kubernetes-native 事务管理)
  • AI 辅助:基于机器学习猜测事务失败概率,动态调解赔偿战略

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

反转基因福娃

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表