ShardingSphere分库分表

一、分库分表

需求分析:

  • 创建数据库 sharding_db1和sharding_db1
  • 在数据库创建两张表 course_1 和 course_2
  • 数据库规则:如果课程 id 是偶数,则添加 sharding_db1库,如果是奇数添加到 sharding_db2库。
  • 数据表规则:如果课程 id 是偶数,则添加 course_1表,如果是奇数添加到 course_2表。

1、application.properties 配置文件

在项目 application.properties 配置文件中进行配置。

# 配置真实数据源
spring.shardingsphere.datasource.names=db1,db2
# 配置第1个数据源
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/sharding_db1?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=123456
# 配置第2个数据源
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/sharding_db2?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=123456

# 指定库表的分布情况:分库,分表
spring.shardingsphere.sharding.tables.course.actual-data-nodes=db$->{1..2}.course_$->{1..2}
# 指定表的主键生成策略,雪花算法
spring.shardingsphere.sharding.tables.course.key-generator.column=id
spring.shardingsphere.sharding.tables.course.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.course.key-generator.props.worker.id=1

#指定分片策略
#1. inline分片策略
#1.1 库策略
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=db$->{id%2+1}
#1.2 表策略
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{id%2+1}

# 打开shardingsphere的sql日志输出。
spring.shardingsphere.props.sql.show=true

# 一个实体类对应两张表,覆盖
spring.main.allow-bean-definition-overriding=true

2、测试代码

1)保存

    @Test
    public void testSave() throws InterruptedException {
        for (int i = 0; i < 20; i++) {
            Course course = new Course();
            course.setGmtCreate(new Date());
            course.setName("java");
            course.setUserId(1001L + i);
            course.setStatus("1");

            TimeUnit.MILLISECONDS.sleep(50);
            int count = courseMapper.insert(course);
            System.out.println("id ->" + course.getId());
        }

    }

数据按照我们的分库分表规则落库ok。

二、分片策略

目前提供5种分片策略:

  • 行表达式分片策略,对应InlineShardingStrategy。
  • 标准分片策略,对应StandardShardingStrategy。
  • 复合分片策略,对应ComplexShardingStrategy。
  • Hint分片策略,对应HintShardingStrategy。
  • 不分片策略,对应NoneShardingStrategy。

1、行表达式分片策略

对应InlineShardingStrategy。使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用。

1)在 application.properties 配置文件中进行配置。

#1. inline分片策略
#1.1 库策略
spring.shardingsphere.sharding.tables.course.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.course.database-strategy.inline.algorithm-expression=db$->{id%2+1}
#1.2 表策略
spring.shardingsphere.sharding.tables.course.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.course.table-strategy.inline.algorithm-expression=course_$->{id%2+1}

2、标准分片策略

对应StandardShardingStrategy。提供对SQL语句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持单分片键,StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。

1)在 application.properties 配置文件中进行配置

#2. standard标准分片策略: in eq between
#2.1 库策略
spring.shardingsphere.sharding.tables.course.table-strategy.standard.sharding-column=id
spring.shardingsphere.sharding.tables.course.table-strategy.standard.precise-algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.standard.MyPreciseTableShardingAlgorithm
spring.shardingsphere.sharding.tables.course.table-strategy.standard.range-algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.standard.MyRangeTableShardingAlgorithm
##2.2 库策略
spring.shardingsphere.sharding.tables.course.database-strategy.standard.sharding-column=id
spring.shardingsphere.sharding.tables.course.database-strategy.standard.precise-algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.standard.MyPreciseDSShardingAlgorithm
spring.shardingsphere.sharding.tables.course.database-strategy.standard.range-algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.standard.MyRangeDSShardingAlgorithm

库与表的分片策略需要我们自定义。

2)库策略算法

/**
 * 自定义扩展的精确分片算法
 */
public class MyPreciseDSShardingAlgorithm implements PreciseShardingAlgorithm<Long> {

    /**
     * @param availableTargetNames 有效的数据源或表的名字。对应配置文件中配置的数据源信息
     * @param shardingValue 包含 逻辑表名、分片列和分片列的值。
     * @return 返回目标结果
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        //实现db$->{id%2+1} 分库策略
        BigInteger shardingValueB = BigInteger.valueOf(shardingValue.getValue());
        BigInteger resB = (shardingValueB.mod(new BigInteger("2"))).add(new BigInteger("1"));
        String key =  "db"+resB ;
        if(availableTargetNames.contains(key)){
            return key;
        }
        throw new UnsupportedOperationException(" route "+key+" is not supported. please check your config");
    }
}
/**
 * 自定义扩展的范围分片算法。
 */
public class MyRangeDSShardingAlgorithm implements RangeShardingAlgorithm<Long> {

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
        return availableTargetNames;
    }
}

3)表策略算法

public class MyPreciseTableShardingAlgorithm implements PreciseShardingAlgorithm<Long> {

    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        //实现按照 = 或 IN 进行精确分片。
        //例如 select * from course where id = 1 or id in (1,3,5)
        //实现course_$->{cid%2+1} 分表策略
        BigInteger shardingValueB = BigInteger.valueOf(shardingValue.getValue());
        BigInteger resB = shardingValueB.mod(new BigInteger("2"))
                .add(new BigInteger("1"));
        String key =  shardingValue.getLogicTableName()+"_"+resB ;
        if(availableTargetNames.contains(key)){
            return key;
        }
        throw new UnsupportedOperationException(" route "+key+" is not supported. please check your config");
    }
}
public class MyRangeTableShardingAlgorithm implements RangeShardingAlgorithm<Long> {

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
        //实现按照 Between 进行范围分片。
        //例如 select * from course where id between 2000 and 3000;
        Long lowerEndpoint = shardingValue.getValueRange().lowerEndpoint();//2000
        Long upperEndpoint = shardingValue.getValueRange().upperEndpoint();//3000
        //实现course_$->{(3000 -2000 )%2+1} 分片策略
//        return Arrays.asList(shardingValue.getLogicTableName()+"_"+shardingValue.getLogicTableName() + ((upperEndpoint - lowerEndpoint) % 2 + 1));
        //对于我们这个奇偶分离的场景,大部分范围查询都是要两张表都查。
        return Arrays.asList(shardingValue.getLogicTableName()+"_1",shardingValue.getLogicTableName()+"_2");
    }
}

4)测试查询
在这里插入图片描述

3、复合分片策略

对应ComplexShardingStrategy。复合分片策略。提供对SQL语句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现,提供最大的灵活度。

1)在 application.properties 配置文件中进行配置

#3. complex复杂分片策略:复杂查询
##3.1 库策略
spring.shardingsphere.sharding.tables.course.table-strategy.complex.sharding-columns= cid, user_id
spring.shardingsphere.sharding.tables.course.table-strategy.complex.algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.complex.MyComplexTableShardingAlgorithm
##3.2 库策略
spring.shardingsphere.sharding.tables.course.database-strategy.complex.sharding-columns=cid, user_id
spring.shardingsphere.sharding.tables.course.database-strategy.complex.algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.complex.MyComplexDSShardingAlgorithm

2)策略算法

public class MyComplexDSShardingAlgorithm  implements ComplexKeysShardingAlgorithm<Long> {

    /**
     *
     * @param availableTargetNames 目标数据源 或者 表 的值。
     * @param shardingValue logicTableName逻辑表名 columnNameAndShardingValuesMap 分片列的精确值集合。 columnNameAndRangeValuesMap 分片列的范围值集合
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
        return availableTargetNames;
    }
}
public class MyComplexTableShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
        //实现按照 Between 进行范围分片。
        //例如 select * from course where id in (1,3,5) and user_id Between 200 and 300;

        Collection<Long> cidCol = shardingValue.getColumnNameAndShardingValuesMap().get("id");
        Range<Long> uageRange = shardingValue.getColumnNameAndRangeValuesMap().get("user_id");

        List<String> result = new ArrayList<>();

        Long lowerEndpoint = uageRange.lowerEndpoint();//200
        Long upperEndpoint = uageRange.upperEndpoint();//300
        //实现自定义分片逻辑 例如可以自己实现 course_$->{cid%2+1}
        for(Long id : cidCol){
            BigInteger idI = BigInteger.valueOf(id);
            BigInteger target = (idI.mod(BigInteger.valueOf(2L))).add(new BigInteger("1"));
            result.add("course_"+target);
        }

        return result;
    }
}

4、Hint分片策略

对应HintShardingStrategy。通过Hint指定分片值而非从SQL中提取分片值的方式进行分片的策略。

注意使用它时有非常多的限制。

1)在 application.properties 配置文件中进行配置

#4. hint强制路由策略:与sql无关
##4.1 库策略
spring.shardingsphere.sharding.tables.course.table-strategy.hint.algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.hint.MyHintTableShardingAlgorithm
##4.2 库策略
spring.shardingsphere.sharding.tables.course.database-strategy.hint.algorithm-class-name=com.charge.learn.shardingsphere.jdbc.study.sharding.strategy.hint.MyHintTableShardingAlgorithm

2)策略算法

public class MyHintDSShardingAlgorithm implements HintShardingAlgorithm<Integer> {
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Integer> shardingValue) {
        return Arrays.asList("db1","db2");
    }
}
public class MyHintTableShardingAlgorithm implements HintShardingAlgorithm<Integer> {
    /**
     *
     * @param availableTargetNames 可选 数据源 和 表 的名称
     * @param shardingValue
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Integer> shardingValue) {
        // 对SQL的零侵入分片方案。shardingValue是通过HintManager.
        // 比如我们要实现将 select * from t_user where user_id in {1,2,3,4,5,.....}; 按照in的第一个值,全部路由到course_1表中。       
        String key = "course_"+shardingValue.getValues().toArray()[0];
        if(availableTargetNames.contains(key)){
            return Arrays.asList(key);
        }
//        return Arrays.asList("course_1");
        throw new UnsupportedOperationException(" route "+key+" is not supported. please check your config");
    }
}

分片策略,有时是针对sql定制的,所以在使用过程中有一定的限制。
参见官网文档: https://shardingsphere.apache.org/document/current/cn/features/sharding/use-norms/sql/

参考文章:

– 求知若饥,虚心若愚。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值