ShardingSphere 分片算法

前言

测试ShardingSphere版本:5.2.0

下面配置中省略部分前缀,仅供参考

自动分片算法 Auto Sharding Alogorithm

自动分片算法通常用在 auto-tables 中,只需配置 actualDataSources 后,其他由分片算法自行解析处理。

注意,通常自动分片算法中的分片表都是在数据源中采用类似轮训的方式进行规律分片的,如:

    db_0.user_0, db_1.user_1, db_2.user_2, db_0.user_3, db_1.user_4, db_2.user_5, ...

也就是 db_{i}.user_{ni + n - 1},n为第几轮

取模 MOD

类似 MySQL的 PATITION 里的 MOD,由ShardingSphere通过分片数和取模的分母,自动计算实际表个数。

属性

名称

类型

描述

sharding-count

int

分片数

案例

该案例实际需要 8 个数据源(也支持单数据源的场景),并且每个数据源中各有 4 个user分表,并且分表格式为 user_${0..31}

        autoTables:
          user:
            logicTable:
            actualDataSources: ds_${0..7} # 数据源inline表达式,会自动识别算法:分片键 % 8 
            shardingStrategy: # 分片策略
              standard:
                shardingColumn: id
                shardingAlgorithmName: mod
shardingAlgorithms:
  mod:
    type: MOD
    props:
      sharding-count: 32 # 分片数

散列取模 HASH_MOD

MOD取模通常使用与数组类型的分片,而HASH_MOD不仅适用于数值也适用于字符串(通过hash值取模)列进行分片。该算法基本和MOD类似

属性

名称

类型

描述

sharding-count

int

分片数

案例

该案例只有一个数据源,但库内有 6个分表,并且按 order_id 的 hash值进行取模计算得到实际表。

        autoTables:
          t_order:
            actual-data-nodes: ds.t_order_$->{0..5}
            table-strategy:
              standard:
                sharding-algorithm-name: t-order-algorithm
                sharding-column: order_id
sharding-algorithms:
  t-order-algorithm:
    type: HASH_MOD
    props:
      sharding-count: '6'

容量范围 VOLUME_RANGE

该算法会根据 (${range-upper} - ${range-lower}) / ${sharding-volume} + 2 来算出实际的分片数量,从而实现自动分片功能。

属性

名称

类型

描述

range-lower

Long

范围下界

range-upper

Long

范围上界

sharding-volume

Long

每个分片容量

案例

  auto-tables:
    user:
      actualDataSources: db_${0..1}
      shardingStrategy:
        standard:
          shardingAlgorithmName: volume
          shardingColumn: id
sharding-algorithms:
  volume:
    type: VOLUME_RANGE
    props:
      range-lower: 0
      range-upper: 20000
      sharding-volume: 10000

要注意,这个算法之所以 + 2 ,实际上包含了两个隐藏表,用于储存小于 range-lower大于 range-upper 这两种情况的数据。

也就是说,上面的例子包含4((20000 - 0) / 10000 + 2)个分片

db_0: 
  - user0: (-∞..0) 
  - user2: [10000..20000) 
db_1:
  - user1: [0..10000) 
  - user3: [20000..+∞)

边界范围 BOUNDARY_RANGE

该算法会根据自定义范围进行分片,如0~100在分片0,100~1000在分片1,1000~1500在分片2等。

属性

名称

类型

描述

sharding-ranges

String

分片范围,多个边界可以用 , 隔开

案例

  auto-tables:
    user:
      actualDataSources: db_${0..1}
      shardingStrategy:
        standard:
          shardingAlgorithmName: boundary
          shardingColumn: id
sharding-algorithms:
  boundary:
    type: BOUNDARY_RANGE
    props:
      sharding-ranges: 10,15,100,12000,16000

在面例子中的范围字符串可以拆分为

-∞..10, 
10..15, 
15..100, 
100..12000, 
12000..16000, 
16000..+∞

实际上 BOUNDARY_RANGE 有点像 VOLUME_RANGE,但 BOUNDARY_RANGE 的更灵活容量长度可变

自动日期间隔 AUTO_INTERVAL

日期间隔将按 时间开始边界时间结束边界 之间的秒数除以 分片秒数 再加 2,从而计算出总分片数。也就是 ({datetime-upper} - {datetime-lower}) / sharding-seconds + 2

这里的加2也是用于补上小于 datetime-lower 大于 datetime-upper 的分片。

属性

名称

类型

描述

datetime-lower

String

分片时间开始边界,格式 yyyy-MM-dd HH:mm:ss

datetime-upper

String

分片时间结束边界,格式 yyyy-MM-dd HH:mm:ss

sharding-seconds

long

按多少秒一个分片进行分片

案例

  auto-tables:
    user:
      actualDataSources: db_${0..1}
      shardingStrategy:
        standard:
          shardingAlgorithmName: auto_interval
          shardingColumn: create_time
auto_interval:
  type: AUTO_INTERVAL
  props:
    datetime-lower: 2022-01-02 00:00:00
    datetime-upper: 2022-01-05 00:00:00
    sharding-seconds: 93600 # 一天

该案例中,会按解析为:

?, 2022-01-02 00:00:00 = 0
2022-01-02 00:00:00, 2022-01-03 00:00:00 = 1
...
2022-01-05 00:00:00, ? = 3

标准分片算法 Standard Sharding Algorithm

以下算法只适用于 standard 策略

行间分片算法 INLINE

行间分片通常用于SQL中单个 =IN 操作的分键字段

属性

名称

类型

描述

algorithm-expression

String

分片表达式

allow-range-query-with-inline-sharding(非必须)

boolean

是否允许范围查询。注意,范围查询时将会忽略分片策略,直接使用全路由

案例

  tables:
    position:
      actualDataNodes: db_${0..1}.position # 该表达式表示 db_0.position, db_1.position
      databaseStrategy:
        standard:
          shardingColumn: id
          shardingAlgorithmName: id-mod
sharding-algorithms:
  id-mod:
    type: INLINE
    props:
      algorithm-expression: db_${id % 2} # 该表达式表示 db_0 或 db_1

时间间隔分片 Interval Sharding Algorithm

该分片算法类似AUTO_INTERVAL,但比它要更加灵活,能够配置日期格式、分片后缀格式等,不过也因此配置更加复杂

属性

名称

类型

描述

默认值

datetime-pattern

String

自定义的日期格式,如:yyyy-MM-dd

datetime-lower

String

分片时间开始边界

datetime-upper(按需)

String

分片时间结束边界

Now

sharding-suffix-pattern

String

库表分片后缀格式(逻辑表_后缀),格式必须和 datetime-interval-unit 一致,如:yyyyMM对应MONTHS

datetime-interval-amount(按需)

int

分片间隔

1

datetime-interval-unit(按需)

String

分片间隔时间单位。可选址参考ChronoUnit类

DAYS

案例

  tables:
    position:
      actualDataNodes: db_${202201..202206}.position # 该表达式表示 db_202201.position, db_202202.position...
      databaseStrategy:
        standard:
          shardingColumn: create_time
          shardingAlgorithmName: month_interval
sharding-algorithms:
  type: INTERVAL
  props:
    datetime-pattern: yyyy-MM-dd HH:mm:ss
    datetime-lower: 2022-01-01 00:00:00
    datetime-interval-unit: MONTHS
    sharding-suffix-pattern: yyyyMM

复合分片算法 Complex Sharding Algorithm

以下算法只适用于 complex 策略

复合行间分片算法 COMPLEX_INLINE

可以使用 INLINE 进行多分片键分片。

属性

名称

类型

描述

sharding-columns(非必须)

String

分片键名称,通常在配置tables信息时指定

algorithm-expression

String

分片表达式

allow-range-query-with-inline-sharding(非必须)

boolean

是否允许范围查询。注意,范围查询时将会忽略分片策略,直接使用全路由

案例

  tables:
    position:
      actualDataNodes: db_${0..1}_${0..2}.position
      databaseStrategy:
        complex:
          shardingColumns: id, oid
          shardingAlgorithmName: uoid_complex
sharding-algorithms:
  uoid_complex:
    type: COMPLEX_INLINE
    props:
      algorithm-expression: db_${id % 2}_${oid % 3} # 该表达式表示 db_0_0 到 db_1_2

自定义 complex 分片算法 {Custome}

实现 ComplexKeysShardingAlgorithm 接口

/**
 * 基于 id 和 城市 的分片算法
 *
 * @author Jayin
 * @email [email protected]
 * @date 2022/10/11
 */
public class IdCityTableShardingAlgorithm implements ComplexKeysShardingAlgorithm {
    private String tablePrefix;
    private int shardingCount;
    /** 配置值需要储存 */
    private Properties props;

    @Override
    public Collection doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {
        // Map的值为 Collection 类型,获取对象时需要取第一个元素
        String city = (String) ((Collection) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("city")).toArray()[0];
        Long id = (Long) ((Collection) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("id")).toArray()[0];
        // 根据表前缀、所在地区和分片得到实际表
        String table = this.tablePrefix + "_" + city + "_" + (id % shardingCount);
        if (!collection.contains(table)) {
            return null;
        }
        return Collections.singleton(table);
    }

    /**
     * 返回配置值,因为后续对每个操作进行创建的算法对象都会获取 最初的配置信息,作为新创建对象的配置原型
     * @return
     */
    @Override
    public Properties getProps() {
        return props;
    }

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

    /**
     * 算法初始化,该部分可按算法需要从 props 中获取参数
     * @param properties
     */
    @Override
    public void init(Properties properties) {
        this.props = properties;
        tablePrefix = StringUtils.defaultString(properties.getProperty("tablePrefix"), "position");
        shardingCount = Integer.parseInt(StringUtils.defaultString(properties.getProperty("shardingCount"), "3"));
    }
}

按 SPI 规范配置复合分片算法键类

resources/META-INF/services/org.apache.shardingsphere.sharding.spi.ShardingAlgorithm 文件中添加自定义主键类全类名

xyz.me4cxy.shardingjdbc.algorithm.IdCityTableShardingAlgorithm

使用复合分片算法

spring.shardingsphere.rules.sharding:
  tables:
    user:
      tableStrategy:
        actualDataNodes: db.user_shenzhen_${0..1}, db.user_guangzhou_${0..1} # 定义深圳、广州两个地区相关表
        complex: # 使用复合算法
          shardingColumns: id, city # 分片字段,也就是doSharding的数据 ComplexKeysShardingValue 来源,多个用 , 隔开
          shardingAlgorithmName: id-city # 采用自定义复合算法,id、城市分片
  sharding-algorithms:
    id-city: # 注册算法
      type: ID_CITY
      props: # 添加算法所需额外配置
        tablePrefix: user # 表前缀
        shardingCount: 2 # 表分片数

Hint分配算法 Hint Sharding Algorithm

以下算法适用于 hint 策略

hint行间分片算法 HINT_INLINE

该算法通过 ${value} 占位符,能够替换 HintManager 中添加值,如果添加多次值时,将会遍历每个字并执行一次 doSharding,适合用在按单个外部参数进行分片的情况。

属性

名称

类型

描述

默认值

algorithm-expression

String

分片表达式,通过 ${value} 注入实际值

${value}

案例

  tables:
    test:
      actualDataNodes: db_${0..1}.test
      databaseStrategy:
        hint:
          shardingAlgorithmName: sys-complex-hint
sharding-algorithms:
  sys-complex-hint:
    type: HINT_INLINE
    props:
      algorithm-expression: db_${value} // 将hint注入的值代入,如 db_1

--- 使用
@Test
public void testHint() {
    try (HintManager hintManager = HintManager.getInstance()) {
        hintManager.addDatabaseShardingValue("test", 1L); // 指定hint注入值
        System.out.println(testService.getById(3L));
    }
}

自定义 hint 分片算法

用于处理使用Hint行分片的场景。对于由非SQL字段来作为分片字段的场景,而是通过其他外部方式来进行分库分表时,可使用SQL Hint灵活注入分片字段。如:根据不同端展示不同数据,而“端”由应用控制。需要通过实现 HintShardingAlgorithm 接口完成分片。

详情参考:ShardingSphere 从源码查看hint为什么失效

基于自定义算法类分片算法 Class Based Sharding Algorithm

以下算法可适用于 standard、complex、hint

由于自定义算法通常需要注册到SPI中,但通过该算法能够配置自定义算法类,从而省去注册SPI的步骤

注意,该算法能够将自身的 props 透传给自定义算法类的实例,所以如果自定义算法需要配置参数可通过 props 进行配置

属性

名称

类型

描述

strategy

String

自定义的算法类使用哪种分片策略

algorithmClassName

String

分片算法的全类名

案例

  tables:
    position:
      actualDataNodes: db_${0..1}_${0..2}.position
      databaseStrategy:
        complex:
          shardingColumns: id, oid
          shardingAlgorithmName: uoid_complex
sharding-algorithms:
  id-city: 
    type: CLASS_BASED
    props: 
      strategy: complex
      algorithmClassName: xyz.me4cxy.shardingjdbc.algorithm.IdCityTableShardingAlgorithm
      # 自定义算法的配置
      tablePrefix: user # 表前缀
      shardingCount: 2 # 表分片数

你可能感兴趣的:(ShardingSphere,java)