ShardingSphere-JDBC 分库分表

springBoot  引入maven

            <dependency>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
                <version>4.0.0-RC1</version>
            </dependency>

application.yml配置

spring:
  shardingsphere:
    datasource:
      names: db1,db2
      db1:
        url: jdbc:mysql://localhost:3306/db1?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: root
        password: root
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
      db2:
        url: jdbc:mysql://localhost:3306/db2?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
        username: root
        password: root
        driver-class-name: com.mysql.cj.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
#      masterslave:
#        # 读写分离配置
#        load-balance-algorithm-type: round_robin #负载均衡策略,round_robin是轮循
#        # 最终的数据源名称
#        name: dataSource #就是bean的名字
#        # 主库数据源名称
#        master-data-source-name: db1
#        # 从库数据源名称列表,多个逗号分隔
#        slave-data-source-names: db2
    sharding:
      default-database-strategy:
        inline:
          sharding-column: order_id #数据库分片策略字段
          algorithm-expression: db${order_id % 2+1} # 配置t_order表分表策略
      tables:
        t_order:
          actual-data-nodes: db$->{1..2}.t_order_$->{0..3}  #配置t_order表分库策略(inline-基于行表达式的分片算法)
          table-strategy:
            inline:  #只适合一个字段 
              sharding-column: order_id   #分表策略字段
              algorithm-expression: t_order_$->{order_id % 2}  #根据order_id%2 找到对应表名
          key-generator:
            column: order_id
            type: SNOWFLAKE
    props:
      sql:
        show: true #打印sql

table-strategy:指定表的分片策略,table-strategy有以下几种策略

1 ) none 表示不分片,所有数据都存储在同一个表中。

2 ) standard 表示使用标准分片策略,根据分片键的值进行范围匹配,将数据路由到对应的分片表中。

        对应StandardShardingStrategy,标准分片策略,根据分片键的值进行范围匹配,将数据路由到对应的分片表中,提供对SQL语句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。RangeShardingAlgorithm是可选的,用于处理BETWEEN AND, >, <, >=, <=分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理。

配置standard策略,我们需要实现PreciseShardingAlgorithm和RangeShardingAlgorithm接口来自定义自己的分片算法,如下所示

application.yml配置

      tables:
t_order:
actual-data-nodes: db$->{1..2}.t_order_$->{0..3} #配置t_order表分库策略(inline-基于行表达式的分片算法)
table-strategy:
standard:
sharding-column: order_id
precise-algorithm-class-name: com.zjf.web.config.standard.MyTablePreciseShardingAlgorithm

分片类

@Component
@Slf4j
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
    /**
     * @param tableNames 对应分片库中所有分片表的集合
     * @param shardingValue 为分片属性,logicTableName 为逻辑表,columnName 分片键,value 为从 SQL 中解析出来的分片键的值
     * @return
     */
    @Override
    public String doSharding(Collection<String> tableNames, PreciseShardingValue<Integer> shardingValue) {
        for (String tableName : tableNames) {
            // 取模算法,分片键 % 表数量
            String value = String.valueOf(shardingValue.getValue() % tableNames.size() );
            log.info("tableName {} value============ {}",tableName,value);
            if (tableName.endsWith(value)) {
                return tableName;
            }
        }
        throw new IllegalArgumentException("分片失败,tableNames:" + tableNames);
    }
}

3 ) inline 表示使用行表达式分片策略,根据分片键的值通过表达式计算得到分片结果,将数据路由到对应的分片表中。

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

      tables:
        t_order:
          actual-data-nodes: db$->{1..2}.t_order_$->{0..3}
          table-strategy:
            inline:
              sharding-column: order_id
              algorithm-expression: t_order_$->{order_id % 2}

4 ) complex 表示使用复合分片策略,可以同时使用多个分片键对数据进行分片计算,将数据路由到对应的分片表中。

        对应ComplexShardingStrategy。复合分片策略。提供对SQL语句中的=, >, <, >=, <=, IN和BETWEEN AND的分片操作支持,ComplexShardingStrategy支持多分片键,如果表是多分片键的,那么需要使用该策略

       使用complex 策略,需要我们自定义一个ComplexShardingAlgorithm实现类,在该实现类定义相关分片算法

@Slf4j
public class MyComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm {
    /**
     *
     * @param availableTargetNames 进行分片的表
     * @param shardingValue 
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection availableTargetNames, ComplexKeysShardingValue shardingValue) {
        List<String> result = new ArrayList<>();

        // 获取分片键列和对应的分片键值
        Map<String, Collection<Long>> columnNameAndShardingValuesMap = shardingValue.getColumnNameAndShardingValuesMap();

        // 遍历分片键列和分片键值
        for (Map.Entry<String, Collection<Long>> entry : columnNameAndShardingValuesMap.entrySet()) {
            String columnName = entry.getKey();
            Collection<Long> shardingValues = entry.getValue();
            log.info("分片键:"+columnName);
            // 根据分片键列和分片键值进行分片逻辑的实现
            for (Long shardingVal : shardingValues) {
                for (Object availableTargetName : availableTargetNames) {
                    String tableName = availableTargetName.toString();
                    String value = String.valueOf(shardingVal % availableTargetNames.size() );
                    if (tableName.endsWith(value)) {
                        result.add(tableName) ;
                    }
                }
            }
        }
        return result;
    }
}

 

posted @ 2024-01-19 12:28  夕阳下的无名草  阅读(101)  评论(0编辑  收藏  举报