Sharding-Complex策略和强制路由(五)

素颜马尾好姑娘i 2023-10-04 23:26 8阅读 0赞

Sharding-Complex策略和Hint策略(五)

Complex策略-复杂策略

业务中分片键不要选择主键,应该选择业务相关列字段。

假设查询时候,条件包括 cid主键,order_type订单类型,由于order_type没有在分片键中,所以所有表字段都会查询。

之前standard、inneline只支持一个字段分片键。

这时候需要使用Complex(复杂策略)他支持多个分片键。

配置文件指定 sharding-column列名配置、complex-algorithm-class-name实现策略类

  1. # 单库分表 配置
  2. spring:
  3. shardingsphere:
  4. datasource:
  5. # 配置数据库名称 相当于给数据源取别名(可以配置多个库,以逗号隔开)
  6. names: m1
  7. # 配置具体数据库连接信息
  8. m1:
  9. type: com.alibaba.druid.pool.DruidDataSource
  10. driverClassName: com.mysql.cj.jdbc.Driver
  11. # 配置 数据库 test
  12. url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
  13. username: root
  14. password: root
  15. # 分片策略
  16. sharding:
  17. # 配置不同表的 分片策略
  18. tables:
  19. # 配置 具体的 逻辑表的 分片策略
  20. t_order:
  21. # t_order 订单表的 主键规则
  22. keyGenerator:
  23. # 主键列
  24. column: order_id
  25. # 主键生成规则 (SNOWFLAKE 雪花算法 生成分布式唯一ID)
  26. type: SNOWFLAKE
  27. # 未知作用
  28. # props:
  29. # worker:
  30. # id: 1
  31. # 配置 t_order 订单表的 具体数据库物理表的映射关系 表达式
  32. actualDataNodes: m1.t_order_$->{
  33. 1..8}
  34. # 表策略
  35. tableStrategy:
  36. #复杂策略
  37. complex:
  38. # 分片列-多列
  39. sharding-column: order_id,order_type
  40. # 实现策略类
  41. algorithm-class-name: com.wnn.sd.algorithm.MyComplexShardingAlgorithm
  42. # 配置是否打印SQL
  43. props:
  44. sql.show: true

复杂策略需要实现ComplexKeysShardingAlgorithm类

  1. package com.wnn.sd.algorithm;
  2. import java.math.BigInteger;
  3. import java.util.ArrayList;
  4. import java.util.Collection;
  5. import java.util.List;
  6. import com.google.common.collect.Range;
  7. import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
  8. import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
  9. import lombok.extern.slf4j.Slf4j;
  10. /**
  11. * 实现复杂分片策略
  12. **/
  13. @Slf4j
  14. public class MyComplexShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
  15. /**
  16. * getColumnNameAndRangeValuesMap和getColumnNameAndShardingValuesMap两种方式获取
  17. *
  18. * 假设sql为
  19. * select * form t_order where between xxx and xxx and order_type in('')
  20. */
  21. @Override
  22. public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
  23. //获取 列名-值-方式1,范围查询
  24. Range<Long> orderIdRange = shardingValue.getColumnNameAndRangeValuesMap().get("order_id");
  25. //获取 列名-值方式2,in查询
  26. Collection<Long> orderTypeList = shardingValue.getColumnNameAndShardingValuesMap().get("order_type");
  27. Long orderIdUpperValue = orderIdRange.upperEndpoint();// 上限
  28. Long orderIdLowerValue = orderIdRange.lowerEndpoint();// 下限
  29. List<String> result = new ArrayList<>();
  30. // todo 范围查询暂无业务
  31. // if (1632276476400000000<orderIdLowerValue && orderIdUpperValue<1632276476400000000){
  32. // result.add(shardingValue.getLogicTableName() + "_1");
  33. // }
  34. // 实现订单类型查询策略
  35. for (Long orderTypeObj : orderTypeList) {
  36. // 主键值转换BigInteger做计算
  37. BigInteger orderType = BigInteger.valueOf(orderTypeObj);
  38. // 取摸算法%2+1
  39. BigInteger target = (orderType.mod(new BigInteger("8"))).add(new BigInteger("1"));
  40. log.info("wn-log-MyRangeShardingAlgorithm + logicTableName {}", target);
  41. result.add(shardingValue.getLogicTableName() + "_" + target);
  42. }
  43. return result;
  44. }
  45. }

其中代码获取值,然后依次做业务判断

  1. //获取 列名-值-方式1,范围查询
  2. Range<Long> orderIdRange = shardingValue.getColumnNameAndRangeValuesMap().get("order_id");
  3. //获取 列名-值方式2,in查询
  4. Collection<Long> orderTypeList = shardingValue.getColumnNameAndShardingValuesMap().get("order_type");

Hint策略-强制路由策略

当我们在业务中有某些特殊情况,想要强行查询某张表。

配置类,可以结合standard策略使用,添加强制路由类 hint-algorithm-class-name

  1. tableStrategy:
  2. standard:
  3. # 分片列
  4. sharding-column: order_id
  5. # 范围分片算法类名称,用于 范围查询 可选。该类需实现 RangeShardingAlgorithm 接口并提供无参数的构造器
  6. range-algorithm-class-name: com.wnn.sd.algorithm.MyRangeShardingAlgorithm
  7. # 精确分片算法类名称,用于 = 和 IN。该类需实现 PreciseShardingAlgorithm 接口并提供无参数的构造器
  8. precise-algorithm-class-name: com.wnn.sd.algorithm.MyPreciseShardingAlgorithm
  9. hint-algorithm-class-name: com.wnn.sd.algorithm.MyHintShardingAlgorithm

使用HintManager类,添加我们要查询的表

  1. /**
  2. * 查询列表数据
  3. */
  4. @Test
  5. public void queryList() {
  6. //手动设置分片键
  7. HintManager hintManager = HintManager.getInstance();
  8. //强制查询表1
  9. hintManager.addTableShardingValue("t_order",1);
  10. List<Order> orders = orderMapper.selectList(null);
  11. orders.forEach(o -> System.out.println(o));
  12. }

实现HintShardingAlgorithm类

  1. package com.wnn.sd.algorithm;
  2. import java.lang.reflect.Array;
  3. import java.math.BigInteger;
  4. import java.util.ArrayList;
  5. import java.util.Arrays;
  6. import java.util.Collection;
  7. import java.util.List;
  8. import com.google.common.collect.Range;
  9. import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
  10. import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
  11. import lombok.extern.slf4j.Slf4j;
  12. import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
  13. import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;
  14. /**
  15. * 强制路由
  16. **/
  17. @Slf4j
  18. public class MyHintShardingAlgorithm implements HintShardingAlgorithm<Long> {
  19. /**
  20. * 简单实现获取表编号,返回对应表名
  21. *
  22. * @param availableTargetNames available data sources or tables's names
  23. * @param shardingValue sharding value
  24. * @return
  25. */
  26. @Override
  27. public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Long> shardingValue) {
  28. String key = shardingValue.getLogicTableName() + "_" + shardingValue.getValues().toArray()[0];//2
  29. if (availableTargetNames.contains(key)){
  30. return Arrays.asList(key);
  31. }
  32. return null;
  33. }
  34. }

发表评论

表情:
评论列表 (有 0 条评论,8人围观)

还没有评论,来说两句吧...

相关阅读