ShardingSphere 分库分表 后的事务

举报
福州司马懿 发表于 2025/10/22 16:50:13 2025/10/22
【摘要】 在 ShardingSphere 中实现分库分表后的分布式事务是一个关键挑战,因为数据被分散到多个数据库实例中,传统的本地事务无法保证跨库操作的原子性。ShardingSphere 提供了多种分布式事务解决方案,适用于不同场景。以下是详细的技术解析和配置指南: 一、ShardingSphere 分布式事务支持ShardingSphere 支持以下三种主流的分布式事务模式:模式适用场景特点XA...

ShardingSphere 中实现分库分表后的分布式事务是一个关键挑战,因为数据被分散到多个数据库实例中,传统的本地事务无法保证跨库操作的原子性。ShardingSphere 提供了多种分布式事务解决方案,适用于不同场景。以下是详细的技术解析和配置指南:


一、ShardingSphere 分布式事务支持

ShardingSphere 支持以下三种主流的分布式事务模式:

模式 适用场景 特点
XA(两阶段提交) 强一致性要求,如金融交易、订单支付等 基于 XA 协议,强一致性但性能较低,依赖数据库的 XA 支持
SEATA(AT 模式) 业务复杂度高、需要全局事务的场景(如订单+库存+支付) 基于 Seata 的 AT 模式,性能较好,但需要引入 Seata 服务端
SAGA 长事务、允许最终一致性的场景(如旅游订单、工作流) 柔性事务,通过补偿机制实现最终一致性,性能高但实现复杂
本地事务(TCC) 适合高并发、短事务的场景(如秒杀系统) 需要业务代码实现 Try-Confirm-Cancel,灵活性高但开发成本大

二、XA 分布式事务(强一致性)

1. 原理

XA 事务基于 两阶段提交(2PC) 协议,通过事务协调器(TM)和资源管理器(RM)保证跨库事务的原子性。

2. 配置步骤

(1)引入依赖

<!-- Spring Boot + ShardingSphere-JDBC -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.3.2</version>
</dependency>
<!-- 数据库驱动(如 MySQL) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

(2)配置数据源和事务

application.yml 中配置分库分表规则和 XA 事务:

spring:
  shardingsphere:
    datasource:
      names: ds0,ds1  # 定义数据源名称
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/db0
        username: root
        password: password
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/db1
        username: root
        password: password
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: ds$->{0..1}.t_order_$->{0..1}  # 分库分表规则
            table-strategy:
              standard:
                sharding-column: order_id
                precise-algorithm-class-name: com.example.OrderTableShardingAlgorithm
            database-strategy:
              standard:
                sharding-column: user_id
                precise-algorithm-class-name: com.example.OrderDatabaseShardingAlgorithm
    props:
      sql-show: true  # 打印 SQL 日志
      # 启用 XA 事务
      transaction-type: XA
      xa-transaction-manager-class-name: org.apache.shardingsphere.transaction.xa.AtomikosXATransactionManager

(3)代码示例

@Service
public class OrderService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional  // 声明式事务(Spring 管理)
    public void createOrder(Long userId, Long orderId) {
        // 插入订单(跨库操作)
        jdbcTemplate.update("INSERT INTO t_order (order_id, user_id, status) VALUES (?, ?, ?)", 
            orderId, userId, "CREATED");
        
        // 更新库存(假设在另一个库)
        jdbcTemplate.update("UPDATE t_inventory SET stock = stock - 1 WHERE product_id = ?", 
            1001);
    }
}

3. 注意事项

  • 性能问题:XA 事务需要全局锁,并发高时可能成为瓶颈。
  • 数据库支持:MySQL 需启用 binlog_format=ROW(推荐 InnoDB 引擎)。
  • 超时设置:调整 max_activesmax_timeout 避免阻塞。

三、SEATA 分布式事务(AT 模式)

1. 原理

SEATA 的 AT 模式通过 全局锁回滚日志 实现无侵入式的分布式事务,性能优于 XA。

2. 配置步骤

(1)部署 SEATA 服务端

  1. 下载 SEATA Server
  2. 修改 file.conf 配置存储模式(如 fileMySQL)。
  3. 启动 SEATA Server:
    sh seata-server.sh -p 8091 -h 127.0.0.1
    

(2)ShardingSphere 集成 SEATA

application.yml 中配置:

spring:
  shardingsphere:
    props:
      transaction-type: SEATA
      seata-enable-auto-data-source-proxy: true  # 自动代理数据源
    # 其他分库分表配置...

(3)业务代码改造

  1. 添加 @GlobalTransactional 注解:
    @Service
    public class OrderService {
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @GlobalTransactional  // SEATA 全局事务
        public void createOrder(Long userId, Long orderId) {
            jdbcTemplate.update("INSERT INTO t_order (...) VALUES (...)");
            jdbcTemplate.update("UPDATE t_inventory SET stock = stock - 1 WHERE ...");
        }
    }
    
  2. resources 下添加 registry.conf(注册中心配置,如 Nacos)。

3. 注意事项

  • 数据源代理:需启用 seata-enable-auto-data-source-proxy
  • 表结构要求:业务表需有主键,且 SEATA 会创建 undo_log 表。
  • 性能优化:调整 SEATA 的 service.vgroupMappingstore.mode

四、SAGA 柔性事务(最终一致性)

1. 原理

SAGA 通过 正向操作 + 补偿操作 实现最终一致性,适用于长事务场景。

2. 配置步骤

(1)定义 SAGA 状态机

编写 JSON 文件(如 order-saga.json):

{
  "Name": "OrderSaga",
  "StartState": "CreateOrder",
  "States": {
    "CreateOrder": {
      "Type": "ServiceTask",
      "ServiceName": "orderService",
      "ServiceMethod": "createOrder",
      "Next": "CompensateOrderOnError"
    },
    "CompensateOrderOnError": {
      "Type": "ServiceTask",
      "ServiceName": "orderService",
      "ServiceMethod": "compensateOrder",
      "IsCompensation": true
    }
  }
}

(2)集成 ShardingSphere

application.yml 中配置:

spring:
  shardingsphere:
    props:
      transaction-type: SAGA
      saga-state-machine-path: classpath:order-saga.json

3. 适用场景

  • 订单超时取消
  • 旅游套餐预订(涉及酒店、机票、保险等多个服务)

五、本地事务(TCC)

1. 原理

TCC(Try-Confirm-Cancel)通过业务代码实现两阶段提交:

  1. Try:预留资源(如冻结库存)。
  2. Confirm:确认操作(如实际扣减库存)。
  3. Cancel:回滚操作(如释放冻结库存)。

2. 代码示例

public interface TccOrderService {
    @Transactional
    boolean tryOrder(Long orderId);  // 预留资源

    @Transactional
    boolean confirmOrder(Long orderId);  // 确认提交

    @Transactional
    boolean cancelOrder(Long orderId);  // 回滚
}

3. 适用场景

  • 秒杀系统(高并发、短事务)
  • 支付系统(需要精确控制资源)

六、性能对比与选型建议

模式 一致性 性能 实现复杂度 适用场景
XA 强一致 金融交易
SEATA 强一致 订单+库存+支付
SAGA 最终一致 旅游订单、工作流
TCC 最终一致 极高 极高 秒杀、高并发支付

推荐选型

  • 优先 SEATA:平衡一致性与性能,适合大多数业务。
  • 高并发场景选 TCC:如秒杀系统。
  • 长事务选 SAGA:如旅游订单。

七、常见问题与排查

1. XA 事务超时

  • 原因:网络延迟或数据库锁等待。
  • 解决:调整 max_activesmax_timeout
    spring:
      shardingsphere:
        props:
          xa-transaction-manager-class-name: org.apache.shardingsphere.transaction.xa.AtomikosXATransactionManager
          max-actives: 200
          max-timeout: 300000  # 5分钟
    

2. SEATA 报错 No available service

  • 原因:SEATA Server 未注册或网络不通。
  • 解决
    1. 检查 SEATA Server 日志。
    2. 确认 registry.conf 配置正确(如 Nacos 地址)。

3. 分库分表后事务不生效

  • 原因:未正确配置 transaction-type
  • 解决:检查 application.yml 是否包含:
    spring:
      shardingsphere:
        props:
          transaction-type: XA  # 或 SEATA/SAGA
    

八、总结

  • XA:简单但性能低,适合强一致性场景。
  • SEATA:平衡性能与一致性,推荐作为首选方案。
  • SAGA/TCC:适合柔性事务或高并发场景,但实现复杂。

通过合理选择事务模式,可以确保 ShardingSphere 分库分表后的数据一致性,同时兼顾系统性能。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。