sharding-jdbc四种分片策略使用详解

 更新时间:2025年12月08日 08:38:24   作者:帅宇Yeah~  
本文介绍了四种分片策略:标准分片、行表达式分片、复合分片和Hint分片,每种策略都提供了配置文件示例和解释,以帮助用户更好地理解和使用分片技术

标准分片策略(standard)

1、精确分片

配置文件

spring:
  shardingsphere:
    #开启sql显示
    props:
      sql:
        show: true
    datasource:
      # 配置数据源
      names: db0,db1
      db0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
      db1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
    sharding:
      #唯一库数据
      default-data-source-name: db0
      #分库
      default-database-strategy:
        standard:
          # 添加数据分库字段(根据字段插入数据到那个表)
          sharding-column: id
          #精确分片
          precise-algorithm-class-name: com.example.sharding_test.strategy.database.DatabasePreciseAlgorithm
      #分表
      tables:
        #表名
        db_user:
          actual-data-nodes: db$->{0..1}.db_user_$->{0..2}
          key-generator:
            column: id  # 主键ID
            type: SNOWFLAKE  # 生成策略雪花id
          table-strategy:
            standard:
              sharding-column: id
              #精确分片
              precise-algorithm-class-name: com.example.sharding_test.strategy.table.TablePreciseAlgorithm

分库规则

package com.example.sharding_test.strategy.database;

import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;

/**
 * 精确分片
 *
 * @author shuai
 * @since 2023-03-19
 */
public class DatabasePreciseAlgorithm implements PreciseShardingAlgorithm<Long> {
    /**
     * 精确分片
     * @param collection 数据源集合
     * @param preciseShardingValue 分片参数
     * @return 数据库
     */
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
        //分片键的值
        Long value = preciseShardingValue.getValue();
        String dbName = "db" + (value % 2);
        if(!collection.contains(dbName)){
           throw new UnsupportedOperationException("数据源"+ dbName + "不存在");
        }
        return dbName;
    }
}

分表规则

package com.example.sharding_test.strategy.table;

import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;

/**
 * 精确分片
 *
 * @author shuai
 * @since 2023-03-19
 */
public class TablePreciseAlgorithm implements PreciseShardingAlgorithm<Long> {
    /**
     * 精确分片
     * @param collection 数据源集合
     * @param preciseShardingValue 分片参数
     * @return 数据库
     */
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<Long> preciseShardingValue) {
        //分片键的值
        Long value = preciseShardingValue.getValue();
        String tableName = preciseShardingValue.getLogicTableName() + "_" + (value % 3);
        if(!collection.contains(tableName)){
           throw new UnsupportedOperationException("表"+ tableName + "不存在");
        }
        return tableName;
    }
}

2、范围分片

配置文件

spring:
  shardingsphere:
    #开启sql显示
    props:
      sql:
        show: true
    datasource:
      # 配置数据源
      names: db0,db1
      db0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
      db1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
    sharding:
      #唯一库数据
      default-data-source-name: db0
      #分库
      default-database-strategy:
        standard:
          # 添加数据分库字段(根据字段插入数据到那个表)
          sharding-column: id
          #精确分片
          precise-algorithm-class-name: com.example.sharding_test.strategy.database.DatabasePreciseAlgorithm
          #范围分片
          range-algorithm-class-name: com.example.sharding_test.strategy.database.DatabaseRangeAlgorithm          
      #分表
      tables:
        #表名
        db_user:
          actual-data-nodes: db$->{0..1}.db_user_$->{0..2}
          key-generator:
            column: id  # 主键ID
            type: SNOWFLAKE  # 生成策略雪花id
          table-strategy:
            standard:
              sharding-column: id
              #精确分片
              precise-algorithm-class-name: com.example.sharding_test.strategy.table.TablePreciseAlgorithm
              #范围分片
              range-algorithm-class-name: com.example.sharding_test.strategy.table.TableRangeAlgorithm

分库规则

package com.example.sharding_test.strategy.database;

import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;

import java.util.Collection;

/**
 * 范围分片
 *
 * @author shuai
 * @since 2023-03-19
 */
public class DatabaseRangeAlgorithm implements RangeShardingAlgorithm<Long> {
    /**
     * 范围分片
     * @param collection 数据源集合
     * @param rangeShardingValue 分片参数
     * @return 直接返回源
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        return collection;
    }
}

分表规则

package com.example.sharding_test.strategy.table;

import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;

import java.util.Arrays;
import java.util.Collection;

/**
 * 范围分片
 *
 * @author shuai
 * @since 2023-03-19
 */
public class TableRangeAlgorithm implements RangeShardingAlgorithm<Long> {
    /**
     * 范围分片
     * @param collection 数据源集合
     * @param rangeShardingValue 分片参数
     * @return 直接返回源
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Long> rangeShardingValue) {
        //逻辑表名称
        String logicTableName = rangeShardingValue.getLogicTableName();
        return Arrays.asList(logicTableName+"_0",logicTableName+"_1",logicTableName+"_2");
    }
}

行表达式分片策略(inline)

配置文件(需要注释其他的分片规则)

spring:
  shardingsphere:
    #开启sql显示
    props:
      sql:
        show: true
    datasource:
      # 配置数据源
      names: db0,db1
      db0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
      db1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
    sharding:
      #唯一库数据
      default-data-source-name: db0
      #分库
      default-database-strategy:
#        standard:
#          # 添加数据分库字段(根据字段插入数据到那个表)
#          sharding-column: id
#          #精确分片
#          precise-algorithm-class-name: com.example.sharding_test.strategy.database.DatabasePreciseAlgorithm
#          #范围分片
#          range-algorithm-class-name: com.example.sharding_test.strategy.database.DatabaseRangeAlgorithm
        inline:
          # 添加数据分表字段(根据字段插入数据到那个表)
          sharding-column: id
          # 分片算法表达式 => 通过id取余
          algorithm-expression: db$->{id % 2}
      #分表
      tables:
        #表名
        db_user:
          actual-data-nodes: db$->{0..1}.db_user_$->{0..2}
          key-generator:
            column: id  # 主键ID
            type: SNOWFLAKE  # 生成策略雪花id
          table-strategy:
#            standard:
#              sharding-column: id
#              #精确分片
#              precise-algorithm-class-name: com.example.sharding_test.strategy.table.TablePreciseAlgorithm
#              #范围分片
#              range-algorithm-class-name: com.example.sharding_test.strategy.table.TableRangeAlgorithm
            inline:
              # 添加数据分表字段(根据字段插入数据到那个表)
              sharding-column: id
              # 分片算法表达式 => 通过id取余
              algorithm-expression: db_user_$->{id % 3}

分库规则与分表规则可直接使用groovy脚本

例:db_user_$->{id % 3}

复合分片策略(complex)

配置文件

spring:
  shardingsphere:
    #开启sql显示
    props:
      sql:
        show: true
    datasource:
      # 配置数据源
      names: db0,db1
      db0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
      db1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
    sharding:
      #唯一库数据
      default-data-source-name: db0
      #分库
      default-database-strategy:
#        standard:
#          # 添加数据分库字段(根据字段插入数据到那个表)
#          sharding-column: id
#          #精确分片
#          precise-algorithm-class-name: com.example.sharding_test.strategy.database.DatabasePreciseAlgorithm
#          #范围分片
#          range-algorithm-class-name: com.example.sharding_test.strategy.database.DatabaseRangeAlgorithm
#        #行分片
#        inline:
#          # 添加数据分表字段(根据字段插入数据到那个表)
#          sharding-column: id
#          # 分片算法表达式 => 通过id取余
#          algorithm-expression: db$->{id % 2}
        #复合分片
         complex:
           sharding-columns: id,age
           algorithm-class-name: com.example.sharding_test.strategy.database.DatabaseComplexAlgorithm

      #分表
      tables:
        #表名
        db_user:
          actual-data-nodes: db$->{0..1}.db_user_$->{0..2}
          key-generator:
            column: id  # 主键ID
            type: SNOWFLAKE  # 生成策略雪花id
          table-strategy:
#            standard:
#              sharding-column: id
#              #精确分片
#              precise-algorithm-class-name: com.example.sharding_test.strategy.table.TablePreciseAlgorithm
#              #范围分片
#              range-algorithm-class-name: com.example.sharding_test.strategy.table.TableRangeAlgorithm
#            inline:
#              # 添加数据分表字段(根据字段插入数据到那个表)
#              sharding-column: id
#              # 分片算法表达式 => 通过id取余
#              algorithm-expression: db_user_$->{id % 3}
            #复合分片
            complex:
              sharding-columns: id,age
              algorithm-class-name: com.example.sharding_test.strategy.table.TableComplexAlgorithm

分库规则

package com.example.sharding_test.strategy.database;

import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.assertj.core.util.Lists;

import java.util.Collection;
import java.util.List;

/**
 * 复合分片
 *
 * @author shuai
 * @since 2023-03-19
 */
public class DatabaseComplexAlgorithm implements ComplexKeysShardingAlgorithm<Integer> {


    /**
     *
     * @param collection 数据源集合
     * @param complexKeysShardingValue 分片键的值集合
     * @return 需要查找的数据源集合
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<Integer> complexKeysShardingValue) {
        //获取age的值
        Collection<Integer> ageValues = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("age");
        List<String> dbs = Lists.newArrayList();
        //通过age取模
        ageValues.forEach(item->{
            String dbName = "db"+((item+3)%2);
            dbs.add(dbName);
        });
        return dbs;
    }
}

分表规则

package com.example.sharding_test.strategy.table;

import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.assertj.core.util.Lists;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * 复合分片
 *
 * @author shuai
 * @since 2023-03-19
 */
public class TableComplexAlgorithm implements ComplexKeysShardingAlgorithm<Integer> {

    @Override
    public Collection<String> doSharding(Collection<String> collection, ComplexKeysShardingValue<Integer> complexKeysShardingValue) {
        //获取age的值
        Collection<Integer> ageValues = complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("age");
        List<String> dbs = Lists.newArrayList();
        //通过age取模
        ageValues.forEach(item->{
            String dbName = "db_user_"+((item+3)%3);
            dbs.add(dbName);
        });
        return dbs;
    }
}

Hint分片策略(hint)

配置文件(需要注释其他的分片规则)

spring:
  shardingsphere:
    #开启sql显示
    props:
      sql:
        show: true
    datasource:
      # 配置数据源
      names: db0,db1
      db0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
      db1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3306/sharding_test_1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
    sharding:
      #唯一库数据
      default-data-source-name: db0
      #分库
      default-database-strategy:
#        standard:
#          # 添加数据分库字段(根据字段插入数据到那个表)
#          sharding-column: id
#          #精确分片
#          precise-algorithm-class-name: com.example.sharding_test.strategy.database.DatabasePreciseAlgorithm
#          #范围分片
#          range-algorithm-class-name: com.example.sharding_test.strategy.database.DatabaseRangeAlgorithm
        #行分片
        inline:
          # 添加数据分表字段(根据字段插入数据到那个表)
          sharding-column: id
          # 分片算法表达式 => 通过id取余
          algorithm-expression: db$->{id % 2}
#        #复合分片
#         complex:
#           sharding-columns: id,age
#           algorithm-class-name: com.example.sharding_test.strategy.database.DatabaseComplexAlgorithm

      #分表
      tables:
        #表名
        db_user:
          actual-data-nodes: db$->{0..1}.db_user_$->{0..2}
          key-generator:
            column: id  # 主键ID
            type: SNOWFLAKE  # 生成策略雪花id
          table-strategy:
#            standard:
#              sharding-column: id
#              #精确分片
#              precise-algorithm-class-name: com.example.sharding_test.strategy.table.TablePreciseAlgorithm
#              #范围分片
#              range-algorithm-class-name: com.example.sharding_test.strategy.table.TableRangeAlgorithm
#            inline:
#              # 添加数据分表字段(根据字段插入数据到那个表)
#              sharding-column: id
#              # 分片算法表达式 => 通过id取余
#              algorithm-expression: db_user_$->{id % 3}
#            #复合分片
#            complex:
#              sharding-columns: id,age
#              algorithm-class-name: com.example.sharding_test.strategy.table.TableComplexAlgorithm
            #强制分片
            hint:
              algorithm-class-name: com.example.sharding_test.strategy.table.TableHintAlgorithm

分表规则

package com.example.sharding_test.strategy.table;

import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;

import java.util.Arrays;
import java.util.Collection;

/**
 * 精确分片
 *
 * @author shuai
 * @since 2023-03-19
 */
public class TableHintAlgorithm implements HintShardingAlgorithm<Integer> {


    @Override
    public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Integer> hintShardingValue) {
        String logicTableName = hintShardingValue.getLogicTableName();
        String dbName = logicTableName+"_"+hintShardingValue.getValues().toArray()[0];
        return Arrays.asList(dbName);
    }
}

测试hint

    @Test
    void selectHintData(){
        HintManager manager = HintManager.getInstance();
        manager.addTableShardingValue("db_user",2);
        LambdaQueryWrapper<DbUser> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(DbUser::getAge,34);
        List<DbUser> dbUsers = dbUserMapper.selectList(wrapper);
        dbUsers.forEach(System.out::println);
    }

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot中使用Zookeeper实现分布式锁的案例

    SpringBoot中使用Zookeeper实现分布式锁的案例

    本文主要介绍了SpringBoot中使用Zookeeper实现分布式锁的案例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • Java如何获取文件夹下所有压缩包下指定文件

    Java如何获取文件夹下所有压缩包下指定文件

    在Java中,通过遍历文件夹并对压缩包进行解析,可以实现提取指定文件的功能,如文档、PDF等,该过程中可增加过滤条件来适应不同需求,例如文件类型或文件名过滤,该方法适用于处理大量数据时的文件管理和数据提取
    2024-09-09
  • Java 方法的定义与调用详解

    Java 方法的定义与调用详解

    在java中,方法就是用来完成解决某件事情或实现某个功能的办法。方法实现的过程中,会包含很多条语句用于完成某些有意义的功能——通常是处理文本,控制输入或计算数值,这篇文章我们来探究一下方法的定义与调用
    2022-04-04
  • Java和Python现在都挺火,我应该怎么选?

    Java和Python现在都挺火,我应该怎么选?

    这篇文章主要介绍了Java和Python现在都挺火,我应该怎么选?本文通过全面分析给大家做个参考,需要的朋友可以参考下
    2020-07-07
  • JNDI,JTA和JMS简介

    JNDI,JTA和JMS简介

    这篇文章主要介绍了JNDI,JTA和JMS的相关内容,包括中文释义,概念解释等,需要的朋友可以了解下。
    2017-09-09
  • 浅谈Arrays.asList()方法的使用

    浅谈Arrays.asList()方法的使用

    本文主要介绍了Arrays.asList()方法的使用。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • SpringBoot中的Controller用法示例详解

    SpringBoot中的Controller用法示例详解

    Controller是SpringBoot里最基本的组件,他的作用是把用户提交来的请求通过对URL的匹配,分配给不同的接收器,再进行处理,然后向用户返回结果,这篇文章主要介绍了SpringBoot中的Controller用法,需要的朋友可以参考下
    2023-06-06
  • 详解Java中的时区类TimeZone的用法

    详解Java中的时区类TimeZone的用法

    TimeZone可以用来获取或者规定时区,也可以用来计算时差,这里我们就来详解Java中的时区类TimeZone的用法,特别要注意下面所提到的TimeZone相关的时间校准问题.
    2016-06-06
  • JDBC中PreparedStatement详解以及应用场景实例介绍

    JDBC中PreparedStatement详解以及应用场景实例介绍

    PreparedStatement对象代表的是一个预编译的SQL语句,用它提供的setter方法可以传入查询的变量,这篇文章主要给大家介绍了关于JDBC中PreparedStatement详解以及应用场景实例介绍的相关资料,需要的朋友可以参考下
    2024-02-02
  • Spring中@PathVariable和@RequestParam注解的用法区别

    Spring中@PathVariable和@RequestParam注解的用法区别

    这篇文章主要介绍了Spring中@PathVariable和@RequestParam注解的用法区别,@PathVariable 是 Spring 框架中的一个注解,用于将 URL 中的变量绑定到方法的参数上,它通常用于处理 RESTful 风格的请求,从 URL 中提取参数值,并将其传递给方法进行处理,需要的朋友可以参考下
    2024-01-01

最新评论