StandardShardingStrategy策略
只支持单分片键的标准分片策略。
配置参数:standard.sharding-column 分片键;
standard.precise.algorithm-class-name 精确分片算法类名;
standard.range-algorithm.class-name 范围分片算法类名
说明:
其中精确分片算法是必须提供的,而范围分片算法则是可选的.
精确查找是支持in和=,数据的插入是通过精确策略,按照范围查找是按照范围分片支持BETWEEN AND、>、<、>=、<=进行分片的场景
sql和源码
https://gitee.com/zhangjijige/shardingjdbc.git
spring:
main:
allow-bean-definition-overriding: true
shardingsphere:
# 参数配置,显示 sql
props:
sql:
show: true
# 配置数据源
datasource:
# 数据源别名
names: db1
# db1数据源信息
db1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/shardingjdbc?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username: root
password: root
sharding:
# 默认数据源
default-data-source-name: db1
tables:
# 逻辑表名
tbl_order:
# 指定tbl_order的数据节点
actual-data-nodes: db1.tbl_order_$->{0..3}
# 分布式主键配置
key-generator:
# 分布式主键列
column: order_id
# 分布式主键生成策略
type: SNOWFLAKE
# 分表策略
table-strategy:
standard:
sharding-column: order_id
# 精确分片算法
precise-algorithm-class-name: com.example.shardingjdbc.sharding.algorithm.MyPreciseShardingAlgorithm
# 范围分片算法
range-algorithm-class-name: com.example.shardingjdbc.sharding.algorithm.MyRangeShardingAlgorithm
mybatis:
mapper-locations: classpath:mapper/*.xml
当范围和精确策略一起使用的时候,要注意逻辑性,比如插入数据时候按照时间分片,1月份插入1月份数据库,按照范围查询的时候查询1月份到3月份的数据,这样数据是能对上的,不能插入数据按照年插入到不同数据库,查询的时候按照月份查询,数据就对不上了
MyPreciseShardingAlgorithm精确分片策略类
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
/**
* tableNames 对应分片库中所有分片表的集合
* shardingValue 为分片属性,其中 logicTableName 为逻辑表,columnName 分片健(字段),value 为从 SQL 中解析出的分片健的值
*/
@Override
public String doSharding(Collection<String> tableList, PreciseShardingValue<Long> shardingValue) {
for (String table: tableList) {
String orderIdLastValue = String.valueOf(shardingValue.getValue());
int value = Integer.parseInt(orderIdLastValue.substring(orderIdLastValue.length() - 1)) % tableList.size();
if (table.endsWith(String.valueOf(value))) {
return table;
}
}
throw new IllegalArgumentException();
}
}
MyRangeShardingAlgorithm范围策略
public class MyRangeShardingAlgorithm implements RangeShardingAlgorithm<Long>{
@Override
public Collection<String> doSharding(Collection<String> tableNames, RangeShardingValue<Long> shardingValue) {
Set<String> result = new LinkedHashSet<>();
// 获取范围的起始值和终止值
Long leftOrderId = shardingValue.getValueRange().lowerEndpoint();
Long rightOrderId = shardingValue.getValueRange().upperEndpoint();
for (Long curOrderId = leftOrderId; curOrderId <= rightOrderId; ++curOrderId) {
String orderIdStr = String.valueOf(curOrderId);
for (String tableName: tableNames) {
int value = Integer.parseInt(orderIdStr.substring(orderIdStr.length() - 1)) % tableNames.size();
if (tableName.endsWith(String.valueOf(value))) {
result.add(tableName);
}
}
}
return result;
}
}
没有配置分库策略
按照范围查找,主要是针对分表,在数据库方面是要轮询所有的数据库,策略类的入参
image.png
image.png
可以看到tableNames是数据表,数据库呢是要遍历的
image.png
配置分库策略
sharding:
# 默认数据源
# default-data-source-name: db0
tables:
# 逻辑表名
tbl_order:
# 指定tbl_order的数据节点
actual-data-nodes: db$->{0..1}.tbl_order_$->{0..3}
# 分布式主键配置
key-generator:
# 分布式主键列
column: order_id
# 分布式主键生成策略
type: SNOWFLAKE
# 分库策略
database-strategy:
standard:
sharding-column: user_id
precise-algorithm-class-name: com.example.shardingjdbc.sharding.algorithm.DBPreciseShardingAlgorithm
# 分表策略
table-strategy:
standard:
sharding-column: order_id
# 精确分片算法
precise-algorithm-class-name: com.example.shardingjdbc.sharding.algorithm.MyPreciseShardingAlgorithm
# 范围分片算法
range-algorithm-class-name: com.example.shardingjdbc.sharding.algorithm.MyRangeShardingAlgorithm
配置了分库策略
按照DBPreciseShardingAlgorithm类的返回值决定从哪个库获取数据
分库建为user_id 也就是在查询sql的时候要有user_id作为条件,否则遍历所有的数据库
参考源码
org.apache.shardingsphere.core.route.type.standard.StandardRoutingEngine#routeDataSources
这里就不分析源码了,可以通过debug的方式看没有配置分库策略,和配置了分库策略但是sql语句中没有user_id作为条件的情况
网友评论