Sharding JDBC(四) 分片策略一:标准分片策略StandardShardingStrategy

目录

 

一、标准分片策略StandardShardingStrategy

二、StandardShardingStrategy配置实现

分库分表最核心的两点SQL 路由  、 SQL 改写 

 application.properties 配置

精准分库PreciseShardingDBAlgorithm

范围分库RangeShardingDBAlgorithm

精准分表PreciseShardingTableAlgorithm

范围分表RangeShardingTableAlgorithm:


一、标准分片策略StandardShardingStrategy

  • 提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持
  • StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm(精准分片)和RangeShardingAlgorithm(范围分片)两个分片算法
  • PreciseShardingAlgorithm是必选的,用于处理=和IN的分片
  • RangeShardingAlgorithm是可选的,用于处理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND将按照全库路由处理
  • 如果需要使用RangeShardingAlgorithm,必须和PreciseShardingAlgorithm配套使用

二、StandardShardingStrategy配置实现

Sharding -jdbc 在使用分片策略的时候,与分片算法是成对出现的,每种策略都对应一到两种分片算法(不分片策略NoneShardingStrategy除外)

分库分表最核心的两点SQL 路由  、 SQL 改写 

SQL 路由:解析原生SQL,确定需要使用哪些数据库,哪些数据表

Route (路由)引擎:为什么要用Route 引擎呢?

在实际查询当中,数据可能不只是存在一台MYSQL服务器上,

SELECT *  FROM t_order WHERE order _id IN(1,3,6)

数据分布:

ds0.t_order0 (1,3,5,7)

ds1.t_order0(2,4,6)

这个SELECT 查询就需要走2个database,如果这个SQL原封不动的执行,肯定会报错(表不存在),Sharding-jdbc 必须要对这个sql进行改写,将库名和表名 2个路由加上 

SELECT *  FROM ds0.t_order0  WHERE order _id IN(1,3)

SELECT *  FROM ds0.t_order1  WHERE order _id IN(6)

SQL 改写:将SQL 按照一定规则,重写FROM 的数据库和表名(Route 返回路由决定需要去哪些库表中执行SQL)

 

 application.properties 配置

   配置主要分为三个部分

  1. 配置数据源
  2. 分库配置  
  3. 分表配置
# standard.precise-algorithm  标准策略 + 精准分片f算法 SQL 就是  = in
# standard.range-algorithm   标准策略 + 范围分片算法 (主要是between  and )
sharding.jdbc.datasource.names=ds0,ds1

#分库配置
sharding.jdbc.config.sharding.default-database-strategy.standard.sharding-column=user_id

sharding.jdbc.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds0.url=jdbc:mysql://127.0.0.1:5306/ds0?useUnicode=yes&characterEncoding=utf8
sharding.jdbc.datasource.ds0.username=root
sharding.jdbc.datasource.ds0.password=root
sharding.jdbc.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
sharding.jdbc.datasource.ds1.url=jdbc:mysql://127.0.0.1:5306/ds1?useUnicode=yes&characterEncoding=utf8
sharding.jdbc.datasource.ds1.username=root
sharding.jdbc.datasource.ds1.password=root



# standard.precise-algorithm 标准策略下分片算法包含2个 precise + range,range是可选的,但是如果使用 range 就必须同 precise 配套一起使用
# 买precise赠送 range,可以选择不要赠品,但是你不能不买还想白嫖赠品
sharding.jdbc.config.sharding.default-database-strategy.standard.precise-algorithm-class-name=ai.yunxi.sharding.config.PreciseShardingDBAlgorithm
sharding.jdbc.config.sharding.default-database-strategy.standard.range-algorithm-class-name=ai.yunxi.sharding.config.RangeShardingDBAlgorithm

# 设置绑定表
sharding.jdbc.config.sharding.binding-tables=t_order,t_order_item

# t_order分表配置
# 如果分片键相同,可以直接在后面凭拼接 例如 :ds$->{0..1}.t_order$->{0..1},ds$->{0..1}.t_order_item$->{0..1}
sharding.jdbc.config.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order$->{0..1}
sharding.jdbc.config.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
sharding.jdbc.config.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=ai.yunxi.sharding.config.PreciseShardingDBAlgorithm
sharding.jdbc.config.sharding.tables.t_order.table-strategy.standard.range-algorithm-class-name=ai.yunxi.sharding.config.RangeShardingDBAlgorithm

# t_order_item分表配置
sharding.jdbc.config.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item$->{0..1}
sharding.jdbc.config.sharding.tables.t_order_item.table-strategy.standard.sharding-column=order_id
sharding.jdbc.config.sharding.tables.t_order_item.table-strategy.standard.precise-algorithm-class-name=ai.yunxi.sharding.config.PreciseShardingDBAlgorithm
sharding.jdbc.config.sharding.tables.t_order_item.table-strategy.standard.range-algorithm-class-name=ai.yunxi.sharding.config.RangeShardingDBAlgorithm

精准分库PreciseShardingDBAlgorithm

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import java.util.Collection;


/**
 * 自定义实现 精准分片算法(PreciseShardingAlgorithm)接口
 * 数据库DB的精准分片
 * @author Peng zhizhong
 * @version 1.0
 * fileName PreciseShardingDBAlgorithm1
 * createTime 2020/5/11  19:21
 */
public class PreciseShardingDBAlgorithm implements PreciseShardingAlgorithm<Integer> {

    /**
     *
     * @param databaseNames 有效的数据源 或者 表 的名字  databaseNames 就为配置文件中的 配置的数据源信息 -> ds0 , ds1
     * @param shardingValue  SQL 分片列 对应的实际值
     * @return
     */
    @Override
    public String doSharding(Collection<String> databaseNames,
                             PreciseShardingValue<Integer> shardingValue) {
        /*
         * 作用:散列到具体的哪个库里面去
         * shardingValue : SQL -> SELECT *  FROM t_order WHERE order _id IN(1,3,6)
         * shardingValue = [1,3,6]
         * */
        for (String each : databaseNames) {
            /**
             * 此方法如果参数所表示的字符序列是由该对象表示的字符序列的后缀返回true, 否则为false;
             *  请注意,如果参数是空字符串或等于此String对象由equals(Object)方法确定结果为 true。
             *  String Str = new String("This is really not immutable!!");   retVal = Str.endsWith( "immutable!!" )
             *  为true
             *  ds0.endsWith("0") -> true ;
             */
            if (each.endsWith(String.valueOf(shardingValue.getValue() % databaseNames.size()))) {
                //返回相应的数据库
                System.out.println("each"+each);
                return each;
            }
        }
        throw new UnsupportedOperationException();
    }
}

范围分库RangeShardingDBAlgorithm

 

import io.shardingsphere.api.algorithm.sharding.RangeShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;


/**
 * 自定义实现 范围分片算法(RangeShardingAlgorithm)接口
 * 数据库DB的范围分片
 * @author Peng zhizhong
 * @version 1.0
 * fileName RangeShardingDBAlgorithm
 * createTime 2020/5/11  19:21
 */
public class RangeShardingDBAlgorithm implements RangeShardingAlgorithm<Integer> {


    @Override
    public Collection<String> doSharding(final Collection<String> databaseNames,
                                         final RangeShardingValue<Integer> shardingValue) {

        /**
         * 自定义SQL -> SELECT *  FROM t_order WHERE order _id Between 2000 and 4000
         * ds0.t_order: 1000 ~ 3000
         * ds1.t_order: 3001 ~ 5000
         * ds2.t_order: 5001 ~ 7000
         *
         * 执行路由后的SQL 应为:
         * SELECT *  FROM ds0.t_order WHERE order _id Between 2000 and 3000
         * SELECT *  FROM ds1.t_order WHERE order _id Between 3001 and 4000
         */
        Set<String> result = new LinkedHashSet<>();
        // 从sql 中获取 Between 2000 and 4000   的值,将2000 赋值给 lower,  4000 赋值给 upper
        int lower = shardingValue.getValueRange().lowerEndpoint();
        int upper = shardingValue.getValueRange().upperEndpoint();
        for (int i = lower; i <= upper; i++) {
            for (String each : databaseNames) { //ds0,ds1
                if (each.endsWith(i % databaseNames.size() + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }
}

精准分表PreciseShardingTableAlgorithm

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import java.util.Collection;


/**
 * 自定义实现 精准分片算法(PreciseShardingAlgorithm)接口
 * 数据表table的精准分片
 * @author Peng zhizhong
 * @version 1.0
 * fileName PreciseShardingTableAlgorithm
 * createTime 2020/5/11  19:21
 */
public class PreciseShardingTableAlgorithm implements PreciseShardingAlgorithm<Long> {

    /**
     * 注释键 PreciseShardingDBAlgorithm
     * @param tableNames
     * @param shardingValue
     * @return
     */
    @Override
    public String doSharding(Collection<String> tableNames,
                             PreciseShardingValue<Long> shardingValue) {
        for (String key : tableNames) {
            if (key.endsWith(String.valueOf(shardingValue.getValue() % tableNames.size()))) {
                System.out.println("key"+key);
                return key;
            }
        }
        throw new UnsupportedOperationException();
    }

}

范围分表RangeShardingTableAlgorithm:

 

import com.google.common.collect.Range;
import io.shardingsphere.api.algorithm.sharding.RangeShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 自定义实现 范围分片算法(RangeShardingAlgorithm)接口
 * 数据表 table 的范围分片
 * @author Peng zhizhong
 * @version 1.0
 * fileName RangeShardingTableAlgorithm
 * createTime 2020/5/11  19:21
 */
public class RangeShardingTableAlgorithm implements RangeShardingAlgorithm<Integer> {

    @Override
    public Collection<String> doSharding(final Collection<String> tableNames,
                                         final RangeShardingValue<Integer> shardingValue) {
        Set<String> result = new LinkedHashSet<>();
        // 如果between  2000000 and 7000000
        if (Range.closed(2000000,
                7000000).encloses(shardingValue.getValueRange())) {
            for (String each : tableNames) {
                if (each.endsWith("0")) {
                    result.add(each);
                }
            }
        } else {
            throw new UnsupportedOperationException();
        }
        return result;
    }

}
  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值