自定义分片算法实现range查询

经过 ShardingSphere分库分表查询 当中所介绍的 range 查询发现是报错的是不支持的,所以在本文当中主要就是介绍该问题的解决方案,就是自定义分片算法实现 range 查询,首先修改 application.properties 修改 db 与 table 的策略为我们自定义的策略如下:

image-20211213135555248

分表策略:

spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=tid
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=standard-range-table
spring.shardingsphere.rules.sharding.sharding-algorithms.standard-range-table.type=STANDARD_TEST_TAB

分库策略:

spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=tid
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=standard-range-db
spring.shardingsphere.rules.sharding.sharding-algorithms.standard-range-db.type=STANDARD_TEST_DB

然后在我们项目结构当中新建一个包(algorithm),来存放我们自定义实现分片算法的代码,创建两个类 TableStandardAlgorithm.java, DbStandardAlgorithm.java 两个都需要实现一个 StandardShardingAlgorithm 接口,然后覆盖接口的方法, 一个是表的分片算法策略,一个是库的分片算法策略以类的开头名称进行区分:

TableStandardAlgorithm.java

/**
 * @author BNTang
 * @date 2021/12/13
 */
public class TableStandardAlgorithm implements StandardShardingAlgorithm<Long> {
    /**
     * @param tableNames    所有真实表的名称
     * @param shardingValue 条件值
     * @return {@link String}
     */
    @Override
    public String doSharding(Collection<String> tableNames, PreciseShardingValue<Long> shardingValue) {
        String truthTable = shardingValue.getLogicTableName() + "_"
                + BigInteger.valueOf(shardingValue.getValue())
                .mod(new BigInteger("2"));
        if (tableNames.contains(truthTable)) {
            return truthTable;
        }
        throw new UnsupportedOperationException("配置错误,表不存在");
    }

    /**
     * 返回值是一个集合. 这个集合决定了范围查询时 要查询的表有哪些
     *
     * @param collection         集合
     * @param rangeShardingValue 分片值范围
     * @return {@link Collection}<{@link String}>
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        String logicTableName = rangeShardingValue.getLogicTableName();
        return Arrays.asList(logicTableName + "_0", logicTableName + "_1");
    }

    @Override
    public void init() {

    }

    @Override
    public String getType() {
        return "STANDARD_TEST_TBL";
    }
}
  • doSharding,@return {@link String}:当中主要是逻辑就是根据 shardingValue.getValue() 获取到传入的条件值也就是 properties 当中配置的 tid,然后拿着该值进行模以 2 得到一个数,然后在通过 shardingValue.getLogicTableName() 拿到逻辑表拼接计算出的值可得到真实表的名称,然后在判断一下有没有在 tableNames 当中包含如果包含就返回拼接的表名称即可,如果不包含就抛了一个异常,不支持操作的异常
  • doSharding @return {@link Collection}<{@link String}>:略
  • init:略
  • getType @return {@link String}:该方法就返回一个之前在 properties 当中所配置的 type

image-20211213141512063

DbStandardAlgorithm.java

/**
 * @author BNTang
 * @date 2021/12/13
 */
public class DbStandardAlgorithm implements StandardShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Long> shardingValue) {
        for (String each : collection) {
            if (each.endsWith(String.valueOf(shardingValue.getValue() % 2))) {
                return each;
            }
        }
        throw new UnsupportedOperationException("配置错误,库不存在");
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        return Arrays.asList("ds0", "ds1");
    }

    @Override
    public void init() {

    }

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

如上分库的覆盖方法的含义自行参考如上分表的解释即可。运行查询,首先我们先不运行范围查询的,先来看看单个的,运行之后发现报错了:

image-20211213145206607

大致的含义就是说我们没有实现一个 class 来自定义 SPI,关于什么是 SPI 我会在下一章节当中进行介绍也就是说还需要在新建关于实现 SPI 相关的配置类,本文就先只介绍自定义分库分表的策略即可。

posted @ 2021-12-13 14:58  BNTang  阅读(458)  评论(0编辑  收藏  举报