ShardingSphere分库分表实战配置:从单库到水平扩展的全流程

分库分表的决策时机

单表数据量超过5000万行、单库IOPS到达磁盘上限、慢查询频发且索引优化已到瓶颈——这是考虑分库分表的典型信号。分库分表不是银弹,引入后会增加运维复杂度和查询限制。在决定之前,优先尝试:读写分离、冷热数据归档、缓存前置、SQL优化。只有这些手段全部用尽后,才启动分库分表。

ShardingSphere-JDBC核心配置

ShardingSphere-JDBC以JAR包方式嵌入应用,对业务代码零侵入。通过YAML配置分片规则:

mode:
  type: Standalone
  repository:
    type: JDBC

dataSources:
  ds_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://10.0.1.10:3306/order_db_0
    username: root
    password: ${DB_PASSWORD}
  ds_1:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://10.0.1.11:3306/order_db_1
    username: root
    password: ${DB_PASSWORD}

rules:
  - !SHARDING
    tables:
      t_order:
        actualDataNodes: ds_${0..1}.t_order_${0..15}
        tableStrategy:
          standard:
            shardingColumn: order_id
            shardingAlgorithmName: order-table-inline
        databaseStrategy:
          standard:
            shardingColumn: user_id
            shardingAlgorithmName: order-db-mod
        keyGenerateStrategy:
          column: order_id
          keyGeneratorName: snowflake

      t_order_item:
        actualDataNodes: ds_${0..1}.t_order_item_${0..15}
        tableStrategy:
          standard:
            shardingColumn: order_id
            shardingAlgorithmName: order-table-inline
        databaseStrategy:
          standard:
            shardingColumn: user_id
            shardingAlgorithmName: order-db-mod

    shardingAlgorithms:
      order-table-inline:
        type: INLINE
        props:
          algorithm-expression: t_order_${order_id % 16}
          allow-range-query-with-round-robin: true
      order-db-mod:
        type: MOD
        props:
          sharding-count: 2

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

这个配置实现2库×16表=32个分片。user_id决定数据落在哪个库(取模),order_id决定落在哪个表。分库键和分表键不同,这是常见的用户维度分库+订单维度分表的组合策略。

分片键的选择原则

分片键的选择直接决定了查询效率。核心原则:

1. 分片键必须覆盖80%以上的查询条件。如果多数查询不带分片键,会退化为全分片扫描

2. 分片键的值分布要均匀。自增ID做分片键会导致热点,推荐用雪花ID或hash

3. 关联表的分片键要对齐。订单表和订单明细表用同一个分片键(order_id),保证关联查询在同一分片内完成

4. 避免使用会变更的字段做分片键。分片键一旦确定,数据迁移成本极高

跨分片查询与归并排序

分库分表后,部分查询需要扫描多个分片。ShardingSphere支持跨分片查询并自动归并结果:

// 带分片键的查询:路由到单个分片,性能最优
SELECT * FROM t_order WHERE user_id = 1001 AND order_id = 202607290001

// 不带分片键的查询:全分片扫描,性能差
SELECT * FROM t_order WHERE status = 'PAID' AND create_time > '2026-07-01'

// 分页查询:需要在所有分片上执行后归并
SELECT * FROM t_order WHERE user_id = 1001 ORDER BY create_time DESC LIMIT 10

深分页是分库分表场景的性能杀手。LIMIT 100000, 10在单库时只需跳过10万行,但在32分片场景下,每个分片都要返回前100010行到协调层归并,内存和网络开销暴增。解决方案:

// 方案1:游标分页(推荐)
// 用上一页最后一条记录的值作为下次查询起点
SELECT * FROM t_order 
WHERE user_id = 1001 AND create_time < '上一页最后一条的create_time'
ORDER BY create_time DESC LIMIT 10

// 方案2:禁用深分页,强制使用搜索条件缩小范围
// 产品侧限制翻页深度,或提供筛选条件引导用户缩小查询范围

分布式主键生成策略

分库分表后,自增主键不再唯一。ShardingSphere内置多种分布式主键生成器:

// 雪花算法:时间有序,索引友好
keyGenerators:
  snowflake:
    type: SNOWFLAKE
    props:
      worker-id: 1       # 每个实例唯一
      max-vibration-offset: 1  # 防止时钟回拨

// UUID:无序,索引性能差,不推荐用于MySQL InnoDB
// NanoID:短ID,适合对外暴露的ID

雪花ID在MySQL InnoDB中表现最佳,因为聚簇索引按主键顺序写入,避免页分裂。UUID作为主键会导致随机I/O,写入性能下降约30%。

数据迁移:从单库到分库的无缝切换

将存量数据从单库迁移到分库分表,需要双写方案保证不停机:

迁移步骤:
1. 部署ShardingSphere配置,但流量仍走旧单库
2. 开启双写:应用同时写入旧库和新分片库
3. 运行数据同步脚本,将旧库存量数据迁移到新分片库
4. 对比校验:逐表逐行对比新旧库数据一致性
5. 读流量切到新分片库,写流量继续双写
6. 验证读流量正常后,关闭旧库写入
7. 观察一周无异常后,下线旧库

# 数据同步脚本核心SQL(按分片规则路由写入)
INSERT INTO ds_${user_id % 2}.t_order_${order_id % 16}
SELECT * FROM old_db.t_order
WHERE MOD(user_id, 2) = ${ds_id}
  AND MOD(order_id, 16) = ${table_id}

整个迁移过程的关键是步骤4的数据校验。校验不光比行数,还要比关键字段的checksum。建议写校验脚本,每1000行比对一次MD5,发现不一致立即告警并暂停迁移。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/shardingsphere-fen-ku-fen-biao-shi-zhan-pei-zhi-cong-dan-ku/

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

相关推荐