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 {


    /**
     * getColumnNameAndRangeValuesMap和getColumnNameAndShardingValuesMap两种方式获取
     *
     *  假设sql为
     *      select * form t_order where between xxx and xxx and order_type in('')
     */
    @Override
    public Collection doSharding(Collection availableTargetNames, ComplexKeysShardingValue shardingValue) {
        //获取 列名-值-方式1,范围查询
        Range orderIdRange = shardingValue.getColumnNameAndRangeValuesMap().get("order_id");
        //获取 列名-值方式2,in查询
        Collection orderTypeList = shardingValue.getColumnNameAndShardingValuesMap().get("order_type");

        Long orderIdUpperValue = orderIdRange.upperEndpoint();// 上限
        Long orderIdLowerValue = orderIdRange.lowerEndpoint();// 下限

        List result = new ArrayList<>();

        // todo 范围查询暂无业务
//        if (1632276476400000000

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

 //获取 列名-值-方式1,范围查询
        Range orderIdRange = shardingValue.getColumnNameAndRangeValuesMap().get("order_id");
        //获取 列名-值方式2,in查询
        Collection 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 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 {


    /**
     * 简单实现获取表编号,返回对应表名
     * 
     * @param availableTargetNames available data sources or tables's names 
     * @param shardingValue        sharding value
     * @return
     */
    @Override
    public Collection doSharding(Collection availableTargetNames, HintShardingValue shardingValue) {
        String key = shardingValue.getLogicTableName() + "_" + shardingValue.getValues().toArray()[0];//2
        if (availableTargetNames.contains(key)){
            return Arrays.asList(key);
        }
        return null;
    }
}

你可能感兴趣的:(java,ShardingSphere,数据库,java,mysql)