1. 为什么需要分布式事务在传统的单体架构中我们只需要使用本地事务就能保证数据一致性。比如一个电商下单流程在同一个数据库里扣减库存、创建订单、扣减余额用Transactional注解就能轻松搞定。但随着业务发展系统被拆分成多个微服务后问题就来了。想象一下订单服务、库存服务、账户服务各自独立部署数据库也完全隔离。用户下单时如果库存扣减成功了但创建订单时网络超时这时候就会出现库存少了但订单没生成的数据不一致问题。这就是典型的分布式事务场景。我去年就遇到过这样的生产事故大促期间由于分布式事务没处理好导致超卖了200多件商品最后只能人工核对数据并给用户退款。这种问题在微服务架构中会频繁出现所以我们需要引入分布式事务解决方案。2. Seata的核心工作原理Seata是阿里开源的分布式事务框架它的AT模式对开发者最友好。先来看下它的核心组件TC (Transaction Coordinator): 事务协调器维护全局事务状态TM (Transaction Manager): 事务管理器负责开启/提交/回滚全局事务RM (Resource Manager): 资源管理器管理分支事务资源具体工作流程是这样的TM向TC申请开启全局事务生成XID全局事务ID各微服务执行SQL时RM会拦截SQL生成undo_log回滚日志TM向TC发起全局提交/回滚TC调度所有RM完成分支事务的提交或回滚我画个简单示意图[TM] -- 开启事务 -- [TC] [RM1] -- 注册分支 -- [TC] [RM2] -- 注册分支 -- [TC] [TM] -- 提交/回滚 -- [TC] [TC] -- 通知 -- [RM1] [TC] -- 通知 -- [RM2]3. 单机版Seata快速搭建3.1 环境准备首先确保你的环境满足JDK 1.8实测JDK11会报GC错误MySQL 5.7Nacos 1.4.0这里有个坑我踩过Seata 1.4.0版本开始支持JDK11但生产环境建议还是用JDK8更稳定。3.2 数据库初始化需要创建两个关键表全局事务表在seata库CREATE DATABASE seata; USE seata; -- 执行下载包中的db_store.sqlundo_log表在每个业务库-- 在订单库、库存库、账户库都要执行 CREATE TABLE undo_log ( id bigint(20) NOT NULL AUTO_INCREMENT, branch_id bigint(20) NOT NULL, xid varchar(100) NOT NULL, context varchar(128) NOT NULL, rollback_info longblob NOT NULL, log_status int(11) NOT NULL, log_created datetime NOT NULL, log_modified datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY ux_undo_log (xid,branch_id) );3.3 配置文件修改主要修改conf目录下两个文件file.conf存储模式配置store { mode db db { datasource druid dbType mysql driverClassName com.mysql.cj.jdbc.Driver url jdbc:mysql://127.0.0.1:3306/seata?useUnicodetrue user root password 123456 minConn 5 maxConn 30 } }registry.conf注册中心配置registry { type nacos nacos { serverAddr localhost:8848 namespace cluster default } } config { type nacos nacos { serverAddr localhost:8848 namespace group SEATA_GROUP } }4. 高可用集群部署方案4.1 集群架构设计生产环境建议采用这种架构[Nginx] | [Seata Server1] [Seata Server2] [Seata Server3] | | | [Nacos Cluster] [MySQL Cluster]关键点至少部署3个Seata Server形成集群使用Nacos作为配置中心和注册中心数据库采用主从复制4.2 事务分组配置这是Seata集群的核心配置在nacos-config.txt中service.vgroupMapping.default_tx_groupcluster1 service.vgroupMapping.order_tx_groupcluster2然后在客户端配置对应的事务组seata: tx-service-group: order_tx_group这样不同业务可以使用不同的事务分组实现资源隔离。4.3 启动参数优化生产环境启动时需要调整JVM参数sh seata-server.sh -p 8091 -h 192.168.1.100 \ -m db -n 3 \ -e test \ -Xmx2048m -Xms2048m \ -Xmn1024m -XX:SurvivorRatio10参数说明-n服务器节点编号-e环境名称-Xmx堆内存最大值-Xms堆内存初始值5. 生产环境常见问题5.1 版本兼容性问题我整理过版本匹配表Seata版本Spring Cloud Alibaba版本Nacos版本1.4.22021.0.1.02.0.31.5.02021.0.4.02.1.0常见报错No available service null found检查事务组配置cant get cluster nameNacos集群配置错误branch transaction rollback failedundo_log表缺失5.2 性能优化建议根据压测经验给出以下参数建议# file.conf store { db { queryLimit 200 # 提高查询效率 maxWait 10000 # 连接池等待时间(ms) } } # seata-server.properties server.undo.logSaveDays7 # undo日志保留天数 server.recovery.committingRetryPeriod3000 # 重试间隔(ms)6. 真实案例电商下单流程以典型的下单场景为例GlobalTransactional public void createOrder(OrderDTO orderDTO) { // 1. 扣减库存 storageFeignClient.deduct(orderDTO.getSkuCode(), orderDTO.getCount()); // 2. 创建订单 orderService.create(orderDTO); // 3. 扣减余额 accountFeignClient.debit(orderDTO.getUserId(), orderDTO.getAmount()); }关键点所有Feign调用必须开启seata代理每个微服务都要配置seata.enable-auto-data-source-proxytrue异常传播机制要正确建议使用RuntimeException我在实际项目中遇到过这样的坑有个同事在account服务里捕获了异常没有抛出导致事务无法回滚。所以一定要确保异常能传播到事务发起方。7. 监控与运维7.1 控制台部署Seata自带管理控制台部署步骤下载seata-console工程修改application.yml中的nacos配置启动后访问http://ip:7091可以实时查看全局事务列表分支事务状态锁冲突情况7.2 告警配置建议监控以下指标事务成功率低于99%需要告警平均处理时间超过500ms需要优化锁等待超时次数可以与Prometheus集成metrics: enabled: true registryType: compact exporterList: prometheus最后说下我的经验分布式事务不是银弹设计时应该尽量避免跨服务事务。比如可以把库存扣减和订单创建放在同一个服务中用本地事务处理。只有真正需要强一致性的场景才使用Seata。