ShardingJDBC 有哪些分片策略,你用的哪个?

#中间件#面试八股

ShardingJDBC 有哪些分片策略,你用的哪个?

结论:ShardingSphere 5.x 把分片拆成两层——分片算法(Sharding Algorithm)负责「算出分片值」,分片策略(Sharding Strategy)负责「用哪个列、配哪个算法」。内置算法有 INLINE、MOD、HASH_MOD、VOLUME_RANGE、BOUNDARY_RANGE、AUTO_INTERVAL 等;4.x 时代则直接叫 Inline、Standard、Complex、Hint、None 五种策略。生产上最常用的是 MOD、HASH_MOD 配 standard,特殊规则写 CLASS_BASED 自定义。

一、策略与算法对照

版本概念常见取值
5.x分片策略 strategystandard、complex、hint、none
5.x分片算法 algorithmINLINE、MOD、HASH_MOD、VOLUME_RANGE、BOUNDARY_RANGE、AUTO_INTERVAL、CLASS_BASED
4.x策略类型inline、standard、complex、hint、none
策略适用 SQL 形态说明
standard=、IN、BETWEEN 单列最常用,单分片键
complex多列组合分片必须自定义算法
hintSQL 不带分片键由 HintManager 强制指定
none广播表、单库不做分片

二、YAML 配置

spring:
  shardingsphere:
    datasource:
      names: ds0,ds1
      ds0:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://10.0.0.11:3306/order_db
        username: app
        password: ${ORDER_DB_PWD}
      ds1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://10.0.0.12:3306/order_db
        username: app
        password: ${ORDER_DB_PWD}
    rules:
      sharding:
        binding-tables:
          - t_order,t_order_item
        tables:
          t_order:
            actual-data-nodes: ds$->{0..1}.t_order_$->{0..7}
            database-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: db_mod
            table-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: tbl_hash_mod
          t_order_item:
            actual-data-nodes: ds$->{0..1}.t_order_item_$->{0..7}
            database-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: db_mod
            table-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: tbl_hash_mod
        sharding-algorithms:
          db_mod:
            type: MOD
            props:
              sharding-count: 2
          tbl_hash_mod:
            type: HASH_MOD
            props:
              sharding-count: 8

三、自定义算法

public class OrderTimeShardingAlgorithm
        implements StandardShardingAlgorithm<LocalDateTime> {

    private static final LocalDateTime CUTOVER = LocalDateTime.of(2025, 1, 1, 0, 0);

    @Override
    public String doSharding(Collection<String> available,
                             PreciseShardingValue<LocalDateTime> value) {
        String suffix = value.getValue().isAfter(CUTOVER) ? "_new" : "_old";
        return available.stream()
                .filter(t -> t.endsWith(suffix))
                .findFirst()
                .orElseThrow(() -> new IllegalStateException("无可用分片: " + available));
    }

    @Override
    public Collection<String> doSharding(Collection<String> available,
                                         RangeShardingValue<LocalDateTime> value) {
        return available;      // 范围查询扇出全部分片
    }

    @Override
    public String getType() {
        return "ORDER_TIME";
    }
}

注册时把算法 type 改为 CLASS_BASED,并用 props 指定 strategy: STANDARD 与 algorithmClassName。

四、常见追问

Q1:为什么不用 inline 表达式? INLINE 写法简洁(t_order_$->{user_id % 8}),但每次路由都要做表达式求值,压测下开销明显;且不支持范围分片、不便于统一治理。生产更推荐 MOD、HASH_MOD 或自定义算法。

Q2:分片后哪些 SQL 不支持? 跨分片的 UNION、部分子查询、CASE WHEN 中引用分片键、未配绑定表的跨库 JOIN、以及部分形态的 INSERT ... SELECT。上线前用 sql-show 逐条核对改写结果。

Q3:SQL 里没有分片键怎么办? 用 HintManager 强制路由:HintManager.getInstance().addDatabaseShardingValue("t_order", 3),适合后台任务或按租户批量处理。用完务必 close(),它绑在线程上。

小结

  • 5.x 是「策略选列 + 算法算值」两层结构,4.x 把两者合在一起叫策略。
  • 高频场景用 MOD、HASH_MOD 配 standard,特殊规则写 CLASS_BASED。
  • 上线前打开 sql-show,确认每条 SQL 的改写与路由都符合预期。
笔记加载中…