99热99:点燃生活激情,解锁无限可能

核心内容摘要

欧美18:探索无限可能,点燃你的激情
全球资讯触手可及:9.1免费版推特最新版亮点官方版全解析,开启社交新纪元

91.xxxx:数字浪潮中的无限可能与时代印记

分布式事务基础概念

1 本地事务 vs 分布式事务在传统单数据库应用中我们通常使用本地事务来保证数据的一致性。

本地事务的ACID特性由数据库直接支持java// JDBC本地事务示例 Connection conn dataSource.getConnection(); // 获取数据库连接 conn.setAutoCommit(false); // 开启事务 try { // 执行增删改查SQL操作 // update account set balance balance - 100 where id 1; // update account set balance balance 100 where id 2; conn.commit(); // 提交事务 } catch (Exception e) { conn.rollback(); // 事务回滚 } finally { conn.close(); // 关闭连接 }本地事务特点操作单一数据库ACID特性由数据库保证性能高实现简单

2 分布式事务的挑战在微服务架构下一个业务操作可能跨越多个服务、多个数据库text用户下单 → 订单服务(DB

→ 库存服务(DB

→ 账户服务(DB

典型的分布式事务场景跨库事务一个服务需要操作多个不同的数据库分库分表数据水平拆分到多个数据库实例微服务调用链多个服务协同完成一个业务操作面临的挑战如何保证多个数据库操作的原子性如何协调不同服务的提交或回滚如何在高并发下保证性能

两阶段提交2PC协议

1 2PC工作原理两阶段提交协议是分布式事务的基础理论分为两个阶段第一阶段准备阶段Preparetext事务协调者(TC) → 询问 → 所有参与者(RM) 参与者执行事务操作但不提交锁定资源 参与者回复准备好(Yes) / 未准备好(No)第二阶段提交/回滚阶段Commit/Rollbacktext如果所有参与者都回复Yes TC → 发送Commit → 所有RM RM提交事务释放资源 如果有参与者回复No或超时 TC → 发送Rollback → 所有RM RM回滚事务释放资源

2 2PC存在的问题同步阻塞参与者需要锁定资源直到第二阶段完成单点故障协调者故障会导致整个事务阻塞数据不一致第二阶段协调者崩溃可能导致部分参与者提交部分回滚性能问题长时间的锁等待影响系统吞吐量

Seata分布式事务解决方案

1 Seata简介SeataSimple Extensible Autonomous Transaction Architecture是阿里巴巴开源的分布式事务解决方案支持多种事务模式AT模式自动补偿对业务无侵入推荐使用TCC模式手动补偿高性能需要业务实现try/confirm/cancelSaga模式长事务解决方案XA模式基于XA协议的标准实现

2 Seata三大核心角色text┌─────────────────────────────────────────┐ │ Seata Architecture │ ├─────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ TM │────▶│ TC │ │ │ │ (事务管理器)│ │ (事务协调者)│ │ │ └─────────────┘ └─────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ RM │◀────│ RM │ │ │ │ (资源管理器)│ │ (资源管理器)│ │ │ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────┘TCTransaction Coordinator事务协调者独立部署的Server端服务维护全局事务和分支事务的状态驱动全局事务提交或回滚TMTransaction Manager事务管理器嵌入在业务应用中定义全局事务边界开始、提交、回滚通过GlobalTransactional注解标记事务方法RMResource Manager资源管理器嵌入在业务应用中管理分支事务的资源数据库连接向TC注册分支事务并报告状态

3 Seata事务生命周期text

TM → TC: 开启全局事务生成XID XID: 全局唯一事务ID在调用链中传递

RM → TC: 注册分支事务 将本地事务关联到全局事务XID

业务执行阶段 各服务执行业务SQL生成undo_log

TM → TC: 提交/回滚全局事务 根据业务结果决定事务最终状态

TC → RM: 驱动分支事务提交/回滚 异步执行第二阶段操作

Seata Server环境搭建

1 部署模式选择Seata Server支持三种存储模式模式说明适用场景file单机模式数据存本地文件开发测试环境db高可用模式数据存数据库生产环境需要高可用redis高性能模式数据存Redis高性能场景

2 DB模式 Nacos部署步骤步骤1下载Seata Serverbash# 从GitHub下载 wget https://github.com/seata/seata/releases/download/v

1.

0/seata-server-

1.

7.

zip unzip seata-server-

1.

7.

zip cd seata步骤2创建数据库表执行MySQL脚本创建Seata Server所需表结构sql-- 创建seata数据库 CREATE DATABASE IF NOT EXISTS seata; USE seata; -- 执行官方提供的建表脚本 -- 下载地址https://github.com/seata/seata/blob/v

1.

0/script/server/db/mysql.sql -- 主要包含global_table、branch_table、lock_table等步骤3配置Nacos注册中心修改conf/application.ymlyamlseata: registry: type: nacos nacos: application: seata-server server-addr:

127.

0.

1:8848 group: SEATA_GROUP namespace: your-namespace-id cluster: default步骤4配置Nacos配置中心修改conf/application.yml配置中心设置yamlseata: config: type: nacos nacos: server-addr:

127.

0.

1:8848 namespace: your-namespace-id group: SEATA_GROUP data-id: seataServer.properties上传配置到Nacosbash# 修改script/config-center/config.txt store.modedb store.db.driverClassNamecom.mysql.cj.jdbc.Driver store.db.urljdbc:mysql://

127.

0.

1:3306/seata?useUnicodetruerewriteBatchedStatementstrue store.db.userroot store.db.passwordyour_password # 事务分组配置 service.vgroupMapping.default_tx_groupdefault service.default.grouplist

127.

0.

1:8091步骤5启动Seata Serverbash# Linux/Mac ./bin/seata-server.sh # Windows .\bin\seata-server.bat访问控制台http://localhost:7091默认账号密码seata/seata

微服务整合Seata AT模式实战

1 业务场景用户下单模拟电商下单场景涉及三个微服务订单服务创建订单记录库存服务扣减商品库存账户服务扣减用户余额

2 环境准备版本兼容性组件版本Spring Boot

3.

2Spring Cloud

2022.

0Spring Cloud Alibaba

2022.

0.

0Seata

1.

0父POM依赖管理xmldependencyManagement dependencies dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-alibaba-dependencies/artifactId version

2022.

0.

0/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement

3 微服务配置

添加依赖xml!-- Seata分布式事务 -- dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-seata/artifactId /dependency !-- 数据库相关 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version

8.

33/version /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version

3.

5.

1/version /dependency

创建undo_log表AT模式必需在每个微服务的业务数据库中执行sqlCREATE TABLE IF NOT EXISTS undo_log ( branch_id BIGINT NOT NULL COMMENT branch transaction id, xid VARCHAR(

NOT NULL COMMENT global transaction id, context VARCHAR(

NOT NULL COMMENT undo_log context, such as serialization, rollback_info LONGBLOB NOT NULL COMMENT rollback info, log_status INT(

NOT NULL COMMENT 0:normal status,1:defense status, log_created DATETIME(

NOT NULL COMMENT create datetime, log_modified DATETIME(

NOT NULL COMMENT modify datetime, UNIQUE KEY ux_undo_log (xid, branch_id), INDEX ix_log_created (log_created) ) ENGINE InnoDB AUTO_INCREMENT 1 DEFAULT CHARSET utf8mb4 COMMENT AT transaction mode undo table;

配置application.ymlyamlspring: application: name: order-service datasource: url: jdbc:mysql://localhost:3306/order_db?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver seata: application-id: ${spring.application.name} # 事务分组需要与Server端配置对应 tx-service-group: default_tx_group registry: type: nacos nacos: application: seata-server server-addr:

127.

0.

1:8848 group: SEATA_GROUP namespace: your-namespace-id config: type: nacos nacos: server-addr:

127.

0.

1:8848 group: SEATA_GROUP namespace: your-namespace-id data-id: seataServer.properties # 开启数据源代理必须 enable-auto-data-source-proxy: true

数据源配置类javaConfiguration public class DataSourceConfig { Bean ConfigurationProperties(prefix spring.datasource) public DataSource dataSource() { return new DruidDataSource(); } // Seata会自动代理数据源无需手动配置 // 注意不能使用Primary注解否则会与Seata的代理冲突 }

4 业务代码实现

订单服务事务发起者javaService Slf4j public class OrderServiceImpl implements OrderService { Autowired private OrderMapper orderMapper; Autowired private StorageFeignService storageFeignService; Autowired private AccountFeignService accountFeignService; Override GlobalTransactional( name createOrder, // 全局事务名称 rollbackFor Exception.class, // 回滚异常类型 timeoutMills 30000 // 超时时间毫秒 ) public Order saveOrder(OrderVo orderVo) { log.info( 用户下单 ); log.info(当前XID: {}, RootContext.getXID()); //

创建订单本地事务 Order order new Order(); order.setUserId(orderVo.getUserId()); order.setCommodityCode(orderVo.getCommodityCode()); order.setCount(orderVo.getCount()); order.setMoney(orderVo.getMoney()); order.setStatus(

; // 初始状态 int saveResult orderMapper.insert(order); log.info(保存订单{}, saveResult 0 ? 成功 : 失败); //

扣减库存远程调用 log.info(开始扣减库存商品: {}, 数量: {}, orderVo.getCommodityCode(), orderVo.getCount()); ResponseResultVoid storageResult storageFeignService.deduct( orderVo.getCommodityCode(), orderVo.getCount() ); if (!storageResult.isSuccess()) { throw new BusinessException(扣减库存失败); } //

扣减余额远程调用 log.info(开始扣减余额用户: {}, 金额: {}, orderVo.getUserId(), orderVo.getMoney()); ResponseResultVoid accountResult accountFeignService.debit( orderVo.getUserId(), orderVo.getMoney() ); if (!accountResult.isSuccess()) { throw new BusinessException(扣减余额失败); } //

更新订单状态 order.setStatus(

; // 成功状态 orderMapper.updateById(order); log.info(订单状态更新成功订单ID: {}, order.getId()); return order; } }

库存服务javaService Slf4j public class StorageServiceImpl implements StorageService { Autowired private StorageMapper storageMapper; Override public void deduct(String commodityCode, Integer count) { log.info(库存服务 - 扣减库存开始XID: {}, RootContext.getXID()); // 查询当前库存 Storage storage storageMapper.selectByCommodityCode(commodityCode); if (storage null) { throw new BusinessException(商品不存在); } if (storage.getCount() count) { throw new BusinessException(库存不足); } // 扣减库存 storage.setCount(storage.getCount() - count); storageMapper.updateById(storage); log.info(库存服务 - 扣减库存成功商品: {}, 剩余库存: {}, commodityCode, storage.getCount()); } }

账户服务javaService Slf4j public class AccountServiceImpl implements AccountService { Autowired private AccountMapper accountMapper; Override public void debit(Long userId, BigDecimal money) { log.info(账户服务 - 扣减余额开始XID: {}, RootContext.getXID()); // 查询账户 Account account accountMapper.selectById(userId); if (account null) { throw new BusinessException(账户不存在); } if (account.getBalance().compareTo(money)

{ throw new BusinessException(余额不足); } // 扣减余额 account.setBalance(account.getBalance().subtract(money)); accountMapper.updateById(account); log.info(账户服务 - 扣减余额成功用户: {}, 剩余余额: {}, userId, account.getBalance()); } }

5 测试验证测试1正常下单bash# 正常请求 POST http://localhost:8080/order/create Content-Type: application/json { userId: 1, commodityCode: P001, count: 1, money:

1

00 } # 预期结果订单创建成功库存扣减余额扣减测试2模拟异常回滚java// 在账户服务中模拟异常 Service Slf4j public class AccountServiceImpl implements AccountService { Override public void debit(Long userId, BigDecimal money) { // ... 正常业务逻辑 // 模拟异常 if (money.compareTo(new BigDecimal(

)

{ throw new RuntimeException(模拟余额扣减异常); } // ... 剩余逻辑 } }预期结果订单服务事务回滚订单记录被删除库存服务事务回滚库存数量恢复账户服务未执行扣减操作

Seata AT模式设计原理

1 AT模式核心机制AT模式是一种无侵入的分布式事务解决方案其核心原理text第一阶段执行阶段

执行业务SQL

解析SQL生成前镜像before image和后镜像after image

将前后镜像保存到undo_log表

提交本地事务释放锁资源 第二阶段完成阶段 - 如果全局事务提交异步删除undo_log - 如果全局事务回滚根据undo_log中的前镜像恢复数据

2 执行流程详解第一阶段分支事务执行sql-- 业务SQL示例 UPDATE product SET stock stock - 1 WHERE id 1 AND stock 0; -- Seata代理后执行的操作 --

查询前镜像before image SELECT id, stock FROM product WHERE id 1; --

执行业务SQL UPDATE product SET stock stock - 1 WHERE id 1 AND stock 0; --

查询后镜像after image SELECT id, stock FROM product WHERE id 1; --

插入undo_log INSERT INTO undo_log (xid, branch_id, rollback_info, log_status) VALUES (全局事务XID, 分支事务ID, 前后镜像数据,

; --

提交本地事务 COMMIT;第二阶段全局事务完成提交场景textTC → 所有RM提交请求 RM → 删除对应的undo_log记录 完成回滚场景textTC → 所有RM回滚请求 RM → 查询undo_log获取前镜像 RM → 根据前镜像生成反向SQL并执行 RM → 删除undo_log记录 完成

3 AT模式优势无侵入性业务代码无需改造只需添加注解高性能一阶段提交本地事务释放锁资源高可用支持Seata Server集群部署强一致性通过undo_log保证最终数据一致性自动补偿回滚时自动生成反向SQL

4 AT模式限制仅支持关系型数据库MySQL、Oracle、PostgreSQL等SQL解析限制不支持复杂SQL如子查询、多表关联更新全局锁机制更新同一行数据时会产生全局锁竞争undo_log表管理需要定期清理历史数据

生产环境最佳实践

1 性能优化配置yamlseata: # 客户端配置 client: rm-report-success-enable: false # 是否上报成功状态生产环境关闭 rm-table-meta-check-enable: false # 自动刷新表元数据生产环境关闭 lock: retry-interval: 10 # 获取全局锁重试间隔毫秒 retry-times: 30 # 获取全局锁重试次数 # 服务端配置seataServer.properties service: disableGlobalTransaction: false # 是否禁用全局事务 store: db: max-wait: 5000 # 连接池最大等待时间 query-limit: 100 # 查询限制 transport: thread-factory: boss-thread-prefix: NettyBoss # boss线程前缀 worker-thread-prefix: NettyServerNIOWorker server-executor-thread-prefix: NettyServerBizHandler share-boss-worker: false # 是否共享boss线程 client-selector-thread-prefix: NettyClientSelector client-selector-thread-size: 1 client-worker-thread-prefix: NettyClientWorkerThread

2 监控与运维

Seata控制台监控访问Seata Server控制台默认端口7091查看全局事务状态监控分支事务执行情况分析事务执行时间

集成Prometheus监控yaml# application.yml management: endpoints: web: exposure: include: prometheus,health,info metrics: export: prometheus: enabled: true

日志配置yamllogging: level: io.seata: DEBUG com.alibaba.cloud.seata: INFO file: name: logs/seata-client.log max-size: 50MB max-history:

3

3 故障排查指南

常见问题1无法获取全局锁现象Could not get global lock错误原因多个事务同时更新同一行数据解决方案优化业务逻辑减少热点数据竞争调整锁等待时间和重试次数使用TCC模式替代AT模式

常见问题2undo_log表过大现象磁盘空间不足查询性能下降解决方案定期清理历史undo_logsql-- 清理7天前的undo_log DELETE FROM undo_log WHERE log_created DATE_SUB(NOW(), INTERVAL 7 DAY);配置自动清理任务javaScheduled(cron 0 0 2 * * ?) // 每天凌晨2点执行 public void cleanUndoLog() { // 清理逻辑 }

常见问题3XID未传递现象分支事务无法关联到全局事务解决方案确保Feign/RestTemplate等HTTP客户端正确传递XID检查网络拦截器是否过滤了XID头验证微服务间的网络连通性

八、

总结与展望

1 Seata AT模式适用场景推荐使用场景业务逻辑相对简单SQL不复杂对性能要求较高希望事务尽快提交希望业务代码无侵入改造主要使用MySQL等关系型数据库不推荐场景涉及复杂SQL多表关联、子查询需要处理非关系型数据库业务对实时一致性要求极高

2 与其他模式对比特性AT模式TCC模式Saga模式侵入性无侵入需要编码需要编码性能高中高一致性最终一致强一致最终一致复杂度低高中适用场景简单业务复杂业务长事务

3 学习资源推荐官方文档https://seata.io/zh-cn/GitHub仓库https://github.com/seata/seata实战示例https://github.com/seata/seata-samples分布式事务是微服务架构中的

关键技术点选择合适的解决方案对系统稳定性至关重要。

Seata AT模式以其无侵入性和易用性成为大多数场景下的首选方案。

网站9.1免费入口不用登录破解版-网站9.1免费入口不用登录破解版应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123