sharding-jdbc四种分片策略
一、标准分片策略(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);
}