Sharding-Complex策略和强制路由(五)
Sharding-Complex策略和Hint策略(五)
Complex策略-复杂策略
业务中分片键不要选择主键,应该选择业务相关列字段。
假设查询时候,条件包括 cid主键,order_type订单类型,由于order_type没有在分片键中,所以所有表字段都会查询。
之前standard、inneline只支持一个字段分片键。
这时候需要使用Complex(复杂策略)他支持多个分片键。
配置文件指定 sharding-column列名配置、complex-algorithm-class-name实现策略类
# 单库分表 配置
spring:
shardingsphere:
datasource:
# 配置数据库名称 相当于给数据源取别名(可以配置多个库,以逗号隔开)
names: m1
# 配置具体数据库连接信息
m1:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
# 配置 数据库 test
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
username: root
password: root
# 分片策略
sharding:
# 配置不同表的 分片策略
tables:
# 配置 具体的 逻辑表的 分片策略
t_order:
# t_order 订单表的 主键规则
keyGenerator:
# 主键列
column: order_id
# 主键生成规则 (SNOWFLAKE 雪花算法 生成分布式唯一ID)
type: SNOWFLAKE
# 未知作用
# props:
# worker:
# id: 1
# 配置 t_order 订单表的 具体数据库物理表的映射关系 表达式
actualDataNodes: m1.t_order_$->{
1..8}
# 表策略
tableStrategy:
#复杂策略
complex:
# 分片列-多列
sharding-column: order_id,order_type
# 实现策略类
algorithm-class-name: com.wnn.sd.algorithm.MyComplexShardingAlgorithm
# 配置是否打印SQL
props:
sql.show: true
复杂策略需要实现ComplexKeysShardingAlgorithm类
package com.wnn.sd.algorithm;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
import lombok.extern.slf4j.Slf4j;
/**
* 实现复杂分片策略
**/
@Slf4j
public class MyComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
/**
* getColumnNameAndRangeValuesMap和getColumnNameAndShardingValuesMap两种方式获取
*
* 假设sql为
* select * form t_order where between xxx and xxx and order_type in('')
*/
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
//获取 列名-值-方式1,范围查询
Range<Long> orderIdRange = shardingValue.getColumnNameAndRangeValuesMap().get("order_id");
//获取 列名-值方式2,in查询
Collection<Long> orderTypeList = shardingValue.getColumnNameAndShardingValuesMap().get("order_type");
Long orderIdUpperValue = orderIdRange.upperEndpoint();// 上限
Long orderIdLowerValue = orderIdRange.lowerEndpoint();// 下限
List<String> result = new ArrayList<>();
// todo 范围查询暂无业务
// if (1632276476400000000<orderIdLowerValue && orderIdUpperValue<1632276476400000000){
// result.add(shardingValue.getLogicTableName() + "_1");
// }
// 实现订单类型查询策略
for (Long orderTypeObj : orderTypeList) {
// 主键值转换BigInteger做计算
BigInteger orderType = BigInteger.valueOf(orderTypeObj);
// 取摸算法%2+1
BigInteger target = (orderType.mod(new BigInteger("8"))).add(new BigInteger("1"));
log.info("wn-log-MyRangeShardingAlgorithm + logicTableName {}", target);
result.add(shardingValue.getLogicTableName() + "_" + target);
}
return result;
}
}
其中代码获取值,然后依次做业务判断
//获取 列名-值-方式1,范围查询
Range<Long> orderIdRange = shardingValue.getColumnNameAndRangeValuesMap().get("order_id");
//获取 列名-值方式2,in查询
Collection<Long> orderTypeList = shardingValue.getColumnNameAndShardingValuesMap().get("order_type");
Hint策略-强制路由策略
当我们在业务中有某些特殊情况,想要强行查询某张表。
配置类,可以结合standard策略使用,添加强制路由类 hint-algorithm-class-name
tableStrategy:
standard:
# 分片列
sharding-column: order_id
# 范围分片算法类名称,用于 范围查询 可选。该类需实现 RangeShardingAlgorithm 接口并提供无参数的构造器
range-algorithm-class-name: com.wnn.sd.algorithm.MyRangeShardingAlgorithm
# 精确分片算法类名称,用于 = 和 IN。该类需实现 PreciseShardingAlgorithm 接口并提供无参数的构造器
precise-algorithm-class-name: com.wnn.sd.algorithm.MyPreciseShardingAlgorithm
hint-algorithm-class-name: com.wnn.sd.algorithm.MyHintShardingAlgorithm
使用HintManager类,添加我们要查询的表
/**
* 查询列表数据
*/
@Test
public void queryList() {
//手动设置分片键
HintManager hintManager = HintManager.getInstance();
//强制查询表1
hintManager.addTableShardingValue("t_order",1);
List<Order> orders = orderMapper.selectList(null);
orders.forEach(o -> System.out.println(o));
}
实现HintShardingAlgorithm类
package com.wnn.sd.algorithm;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;
/**
* 强制路由
**/
@Slf4j
public class MyHintShardingAlgorithm implements HintShardingAlgorithm<Long> {
/**
* 简单实现获取表编号,返回对应表名
*
* @param availableTargetNames available data sources or tables's names
* @param shardingValue sharding value
* @return
*/
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Long> shardingValue) {
String key = shardingValue.getLogicTableName() + "_" + shardingValue.getValues().toArray()[0];//2
if (availableTargetNames.contains(key)){
return Arrays.asList(key);
}
return null;
}
}
还没有评论,来说两句吧...