MySQL分库分表实战:ShardingSphere-JDBC水平拆分配置与数据迁移全流程

单表数据量超过500万行后查询性能急剧下降,B+树层级增加导致磁盘IO放大。分库分表将数据分散到多个物理库表,通过路由规则定位数据位置。ShardingSphere-JDBC以JDBC驱动方式嵌入应用,无需独立代理进程,网络开销为零。

分库分表方案选型与架构设计

订单系统按用户ID取模分库、按订单创建时间分表的混合方案。8个库每个库16张表,总计128张物理表,单表数据量控制在200万以内。

# 分片规划
# 分库规则:user_id % 8 -> ds_0 ~ ds_7
# 分表规则:order_date的月份 % 16 -> order_0 ~ order_15
#
# 物理库:ds_0, ds_1, ..., ds_7
# 物理表:t_order_0, t_order_1, ..., t_order_15
# 路由示例:user_id=1001, order_date=2026-07
#   库:1001 % 8 = 1 -> ds_1
#   表:(202607 % 16) = 7 -> t_order_7

分片键选择遵循原则:高频查询条件字段、数据分布均匀、避免跨片查询。订单系统80%查询携带user_id,适合作为分库键。按时间分表便于历史数据归档和冷热分离。

ShardingSphere-JDBC集成与分片配置

Maven依赖:

<dependency>
  <groupId>org.apache.shardingsphere</groupId>
  <artifactId>shardingsphere-jdbc</artifactId>
  <version>5.5.0</version>
</dependency>

application.yml配置:

spring:
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:classpath:sharding-config.yaml

# sharding-config.yaml
dataSources:
  ds_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    props:
      jdbcUrl: jdbc:mysql://192.168.1.10:3306/order_db_0?useSSL=true
      username: root
      password: ${DB_PASS}
      maximumPoolSize: 20
  ds_1:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    props:
      jdbcUrl: jdbc:mysql://192.168.1.11:3306/order_db_1?useSSL=true
      username: root
      password: ${DB_PASS}
      maximumPoolSize: 20
  # ... ds_2 ~ ds_7

rules:
  - !SHARDING
    tables:
      t_order:
        actualDataNodes: ds_${0..7}.t_order_${0..15}
        databaseStrategy:
          standard:
            shardingColumn: user_id
            shardingAlgorithmName: db_mod
        tableStrategy:
          standard:
            shardingColumn: order_date
            shardingAlgorithmName: table_month_mod
        keyGenerateStrategy:
          column: order_id
          keyGeneratorName: snowflake

    shardingAlgorithms:
      db_mod:
        type: MOD
        props:
          sharding-count: 8
      table_month_mod:
        type: INLINE
        props:
          algorithm-expression: t_order_${Integer.parseInt(order_date.toString().replace('-','')) % 16}

    keyGenerators:
      snowflake:
        type: SNOWFLAKE
        props:
          worker-id: 1

SNOWFLAKE生成全局唯一ID,worker-id需在集群中唯一。INLINE表达式支持Groovy语法,可编写复杂分片逻辑。MOD算法简单高效,但不支持动态扩容。如需后续扩容,推荐使用一致性哈希算法。

分布式主键生成与跨片查询处理

// MyBatis-Plus实体配置
@TableName("t_order")
public class Order {
    @TableId(type = IdType.ASSIGN_ID)  // 使用ShardingSphere分配ID
    private Long orderId;
    private Long userId;
    private String orderDate;
    private BigDecimal amount;
    private Integer status;
}

// 分片键查询:直接路由到单库单表,性能最优
Order order = orderMapper.selectOne(
    new LambdaQueryWrapper<Order>()
        .eq(Order::getUserId, 1001L)
        .eq(Order::getOrderId, 999888777L)
);

// 非分片键查询:广播到所有分片,合并结果
List<Order> orders = orderMapper.selectList(
    new LambdaQueryWrapper<Order>()
        .eq(Order::getStatus, 2)
        .ge(Order::getOrderDate, "2026-07-01")
);
// 实际执行8*16=128条SQL,ShardingSphere自动合并结果

非分片键查询触发全路由广播,性能极差。解决方案:建立ElasticSearch二级索引,或将高频查询字段冗余到分片键组合中。分页查询跨片时,ShardingSphere采用流式归并+改写SQL的方式,将LIMIT 10, 20改写为LIMIT 0, 30在各分片执行后内存归并取第10-20条。

数据迁移与双写扩容方案

从单库迁移到分库分表采用双写+数据同步+灰度切分三阶段方案:

# 阶段1:双写(新旧库同时写入)
// 使用ShardingSphere的读写分离+影子库
// 或在应用层AOP拦截写入操作,同步到新分片库
@Around("execution(* com.example.mapper.OrderMapper.*(..))")
public Object dualWrite(ProceedingJoinPoint pjp) throws Throwable {
    Object result = pjp.proceed();  // 写旧库
    // 异步写新分片库
    shardingOrderMapper.insert((Order) pjp.getArgs()[0]);
    return result;
}

# 阶段2:数据全量同步+增量同步
# 使用DataX或Canal同步历史数据
# 全量同步
python datax.py --job order_migration.json
# 增量同步(Canal监听binlog)
# canal订阅旧库binlog,实时同步到新分片库

# 阶段3:灰度切分
# 按user_id取模灰度,10% -> 30% -> 50% -> 100%
# 配置开关控制路由
@Value("${sharding.enable:false}")
private boolean shardingEnable;

public Order queryOrder(Long userId, Long orderId) {
    if (shardingEnable && userId % 10 < grayPercent) {
        return shardingOrderMapper.selectById(orderId);
    }
    return legacyOrderMapper.selectById(orderId);
}

数据校验使用CRC32或MD5对比新旧库数据一致性。全量同步完成后,对比关键表的数据量和抽样数据MD5值。增量同步延迟控制在1秒以内,通过Canal的checkpoint机制保证不丢数据。灰度切分期间保留回滚能力,发现问题可秒级切回旧库。

分库分表后的运维要点

分库分表后DDL操作需通过ShardingSphere的Scaling工具统一执行。在线DDL支持在不停止服务的情况下修改表结构。分布式事务使用XA或BASE模式:XA保证强一致性但性能较差,BASE(最终一致性)通过Seata的TCC/SAGA模式实现,适合高并发场景。定期清理历史数据通过DROP TABLE直接删除物理表,比DELETE高效且不产生binlog。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/mysql-fen-ku-fen-biao-shi-zhan-shardingspherejdbc-shui-ping/

(0)
小编小编
上一篇 8小时前
下一篇 8小时前

相关推荐