complex复合分片算法配置分库分表

经过上一篇 通过SPI实现range查询策略 实现了范围查询之后,那么在本文的开始之前,我在范围查询测试方法当中在加一个条件,来看看查询的结果如何,添加一个 goods_id 查询条件:

image-20211217144236579

@Test
void getOrderBetween() {
    QueryWrapper<Order> qw = new QueryWrapper<>();
    qw.between("tid", 676006592218402816L, 676006593883541505L);
    qw.eq("goods_id", 1005);
    this.orderMapper.selectList(qw).forEach(System.out::println);
}

image-20211217144218722

通过观察运行结果发现,对所有的库和所有的表都进行了查询,其实在我添加了 goods_id 之后是可以精确到某一个库当中的某一张表的,那么如果想要在这种情况下,实现精确的查询,那么就需要用到本文当中所介绍的复合分片算法来进行实现,那么编写套路和之前通过 SPI 扩展 stand 算法差不多。

概述

复合分片策略支持对多个分片健操作

添加配置

image-20211217171327357

# 配置分表策略 主键+分片算法
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.complex.sharding-columns=tid, goods_id
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.complex.sharding-algorithm-name=complex-table
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-table.type=COMPLEX_TEST_TAB
# 配置分库策略  主键+分片算法
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.complex.sharding-columns=tid, goods_id
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.complex.sharding-algorithm-name=complex-db
spring.shardingsphere.rules.sharding.sharding-algorithms.complex-db.type=COMPLEX_TEST_DB

创建算法实现

image-20211217153040194

DbComplexShardingAlgorithm.java

/**
 * @author BNTang
 * @program ShardingSpherePro
 * @date Created in 2021/12/17 017 15:28
 * @description
 **/
public class DbComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
        return null;
    }

    @Override
    public void init() {

    }

    @Override
    public String getType() {
        return null;
    }
}

TableComplexShardingAlgorithm.java

/**
 * @author BNTang
 * @program ShardingSpherePro
 * @date Created in 2021/12/17 017 15:28
 * @description
 **/
public class TableComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
        return null;
    }

    @Override
    public void init() {

    }

    @Override
    public String getType() {
        return null;
    }
}

在之前我们 stand 实现的是 StandardShardingAlgorithm 那么 complex 实现的为 ComplexKeysShardingAlgorithm,然后就可以与 stand 一样在覆盖的方法当中编写你自己的算法逻辑即可,博主的算法实现逻辑如下:

DbComplexShardingAlgorithm.java

/**
 * @author BNTang
 * @program ShardingSpherePro
 * @date Created in 2021/12/17 017 15:28
 * @description
 **/
public class DbComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> collection,
                                         ComplexKeysShardingValue<Long> complexKeysShardingValue) {
        /*tid的范围查询
        Range<Long> tidRange = complexKeysShardingValue.getColumnNameAndRangeValuesMap().get("tid");
        如果是tid的范围查询,则返回对应的库名*/
        Collection<Long> goodsIds = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("goods_id");

        // 如果是goods_id的范围查询,则返回对应的库名
        if (null != goodsIds) {
            return goodsIds.stream()
                    .map(goodsId -> {
                        BigInteger num = BigInteger.valueOf(goodsId).mod(new BigInteger("2"));
                        num = num.add(new BigInteger("1"));
                        return "shardingspheredb" + num;
                    })
                    .collect(Collectors.toList());
        }
        return collection;
    }

    @Override
    public void init() {

    }

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

TableComplexShardingAlgorithm.java

/**
 * @author BNTang
 * @program ShardingSpherePro
 * @date Created in 2021/12/17 017 15:28
 * @description
 **/
public class TableComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> collection,
                                         ComplexKeysShardingValue<Long> complexKeysShardingValue) {
        /*
        tid的范围查询
        Range<Long> tidRange = complexKeysShardingValue.getColumnNameAndRangeValuesMap().get("tid");
        如果是tid的范围查询,则返回对应的库名
        */
        Collection<Long> goodsIds = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("goods_id");

        // 如果是goods_id的范围查询,则返回对应的库名
        if (null != goodsIds) {
            return goodsIds.stream()
                    .map(goodsId -> {
                        BigInteger num = BigInteger.valueOf(goodsId).mod(new BigInteger("2"));
                        return complexKeysShardingValue.getLogicTableName() + "_" + num;
                    })
                    .collect(Collectors.toList());
        }
        return collection;
    }

    @Override
    public void init() {

    }

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

修改 SPI 文件添加算法类的相对路径:

image-20211217171517055

测试

再次运行之前的范围查询带了 goods_id 的查询,运行结果如下,发现,已经成为了精确的查询,查询的库为 shardingspheredb1 当中的 t_order_0 的真实表:

image-20211217171613314

然后再将 goods_id 去掉进行查询,走的就是博主配置的全库全表如下:

image-20211217171937351

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