当前位置:   article > 正文

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

rangeshardingalgorithm

目录

 

一、标准分片策略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. 分表配置
  1. # standard.precise-algorithm 标准策略 + 精准分片f算法 SQL 就是 = in
  2. # standard.range-algorithm 标准策略 + 范围分片算法 (主要是between and )
  3. sharding.jdbc.datasource.names=ds0,ds1
  4. #分库配置
  5. sharding.jdbc.config.sharding.default-database-strategy.standard.sharding-column=user_id
  6. sharding.jdbc.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
  7. sharding.jdbc.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
  8. sharding.jdbc.datasource.ds0.url=jdbc:mysql://127.0.0.1:5306/ds0?useUnicode=yes&characterEncoding=utf8
  9. sharding.jdbc.datasource.ds0.username=root
  10. sharding.jdbc.datasource.ds0.password=root
  11. sharding.jdbc.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
  12. sharding.jdbc.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
  13. sharding.jdbc.datasource.ds1.url=jdbc:mysql://127.0.0.1:5306/ds1?useUnicode=yes&characterEncoding=utf8
  14. sharding.jdbc.datasource.ds1.username=root
  15. sharding.jdbc.datasource.ds1.password=root
  16. # standard.precise-algorithm 标准策略下分片算法包含2个 precise + range,range是可选的,但是如果使用 range 就必须同 precise 配套一起使用
  17. # 买precise赠送 range,可以选择不要赠品,但是你不能不买还想白嫖赠品
  18. sharding.jdbc.config.sharding.default-database-strategy.standard.precise-algorithm-class-name=ai.yunxi.sharding.config.PreciseShardingDBAlgorithm
  19. sharding.jdbc.config.sharding.default-database-strategy.standard.range-algorithm-class-name=ai.yunxi.sharding.config.RangeShardingDBAlgorithm
  20. # 设置绑定表
  21. sharding.jdbc.config.sharding.binding-tables=t_order,t_order_item
  22. # t_order分表配置
  23. # 如果分片键相同,可以直接在后面凭拼接 例如 :ds$->{0..1}.t_order$->{0..1},ds$->{0..1}.t_order_item$->{0..1}
  24. sharding.jdbc.config.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order$->{0..1}
  25. sharding.jdbc.config.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
  26. sharding.jdbc.config.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=ai.yunxi.sharding.config.PreciseShardingDBAlgorithm
  27. sharding.jdbc.config.sharding.tables.t_order.table-strategy.standard.range-algorithm-class-name=ai.yunxi.sharding.config.RangeShardingDBAlgorithm
  28. # t_order_item分表配置
  29. sharding.jdbc.config.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item$->{0..1}
  30. sharding.jdbc.config.sharding.tables.t_order_item.table-strategy.standard.sharding-column=order_id
  31. sharding.jdbc.config.sharding.tables.t_order_item.table-strategy.standard.precise-algorithm-class-name=ai.yunxi.sharding.config.PreciseShardingDBAlgorithm
  32. sharding.jdbc.config.sharding.tables.t_order_item.table-strategy.standard.range-algorithm-class-name=ai.yunxi.sharding.config.RangeShardingDBAlgorithm

精准分库PreciseShardingDBAlgorithm

  1. import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
  2. import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
  3. import java.util.Collection;
  4. /**
  5. * 自定义实现 精准分片算法(PreciseShardingAlgorithm)接口
  6. * 数据库DB的精准分片
  7. * @author Peng zhizhong
  8. * @version 1.0
  9. * fileName PreciseShardingDBAlgorithm1
  10. * createTime 2020/5/11 19:21
  11. */
  12. public class PreciseShardingDBAlgorithm implements PreciseShardingAlgorithm<Integer> {
  13. /**
  14. *
  15. * @param databaseNames 有效的数据源 或者 表 的名字 databaseNames 就为配置文件中的 配置的数据源信息 -> ds0 , ds1
  16. * @param shardingValue SQL 分片列 对应的实际值
  17. * @return
  18. */
  19. @Override
  20. public String doSharding(Collection<String> databaseNames,
  21. PreciseShardingValue<Integer> shardingValue) {
  22. /*
  23. * 作用:散列到具体的哪个库里面去
  24. * shardingValue : SQL -> SELECT * FROM t_order WHERE order _id IN(1,3,6)
  25. * shardingValue = [1,3,6]
  26. * */
  27. for (String each : databaseNames) {
  28. /**
  29. * 此方法如果参数所表示的字符序列是由该对象表示的字符序列的后缀返回true, 否则为false;
  30. * 请注意,如果参数是空字符串或等于此String对象由equals(Object)方法确定结果为 true。
  31. * String Str = new String("This is really not immutable!!"); retVal = Str.endsWith( "immutable!!" )
  32. * 为true
  33. * ds0.endsWith("0") -> true ;
  34. */
  35. if (each.endsWith(String.valueOf(shardingValue.getValue() % databaseNames.size()))) {
  36. //返回相应的数据库
  37. System.out.println("each"+each);
  38. return each;
  39. }
  40. }
  41. throw new UnsupportedOperationException();
  42. }
  43. }

范围分库RangeShardingDBAlgorithm

 

  1. import io.shardingsphere.api.algorithm.sharding.RangeShardingValue;
  2. import io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm;
  3. import java.util.Collection;
  4. import java.util.LinkedHashSet;
  5. import java.util.Set;
  6. /**
  7. * 自定义实现 范围分片算法(RangeShardingAlgorithm)接口
  8. * 数据库DB的范围分片
  9. * @author Peng zhizhong
  10. * @version 1.0
  11. * fileName RangeShardingDBAlgorithm
  12. * createTime 2020/5/11 19:21
  13. */
  14. public class RangeShardingDBAlgorithm implements RangeShardingAlgorithm<Integer> {
  15. @Override
  16. public Collection<String> doSharding(final Collection<String> databaseNames,
  17. final RangeShardingValue<Integer> shardingValue) {
  18. /**
  19. * 自定义SQL -> SELECT * FROM t_order WHERE order _id Between 2000 and 4000
  20. * ds0.t_order: 1000 ~ 3000
  21. * ds1.t_order: 3001 ~ 5000
  22. * ds2.t_order: 5001 ~ 7000
  23. *
  24. * 执行路由后的SQL 应为:
  25. * SELECT * FROM ds0.t_order WHERE order _id Between 2000 and 3000
  26. * SELECT * FROM ds1.t_order WHERE order _id Between 3001 and 4000
  27. */
  28. Set<String> result = new LinkedHashSet<>();
  29. // 从sql 中获取 Between 2000 and 4000 的值,将2000 赋值给 lower, 4000 赋值给 upper
  30. int lower = shardingValue.getValueRange().lowerEndpoint();
  31. int upper = shardingValue.getValueRange().upperEndpoint();
  32. for (int i = lower; i <= upper; i++) {
  33. for (String each : databaseNames) { //ds0,ds1
  34. if (each.endsWith(i % databaseNames.size() + "")) {
  35. result.add(each);
  36. }
  37. }
  38. }
  39. return result;
  40. }
  41. }

精准分表PreciseShardingTableAlgorithm

  1. import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
  2. import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
  3. import java.util.Collection;
  4. /**
  5. * 自定义实现 精准分片算法(PreciseShardingAlgorithm)接口
  6. * 数据表table的精准分片
  7. * @author Peng zhizhong
  8. * @version 1.0
  9. * fileName PreciseShardingTableAlgorithm
  10. * createTime 2020/5/11 19:21
  11. */
  12. public class PreciseShardingTableAlgorithm implements PreciseShardingAlgorithm<Long> {
  13. /**
  14. * 注释键 PreciseShardingDBAlgorithm
  15. * @param tableNames
  16. * @param shardingValue
  17. * @return
  18. */
  19. @Override
  20. public String doSharding(Collection<String> tableNames,
  21. PreciseShardingValue<Long> shardingValue) {
  22. for (String key : tableNames) {
  23. if (key.endsWith(String.valueOf(shardingValue.getValue() % tableNames.size()))) {
  24. System.out.println("key"+key);
  25. return key;
  26. }
  27. }
  28. throw new UnsupportedOperationException();
  29. }
  30. }

范围分表RangeShardingTableAlgorithm:

 

  1. import com.google.common.collect.Range;
  2. import io.shardingsphere.api.algorithm.sharding.RangeShardingValue;
  3. import io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlgorithm;
  4. import java.util.Collection;
  5. import java.util.LinkedHashSet;
  6. import java.util.Set;
  7. /**
  8. * 自定义实现 范围分片算法(RangeShardingAlgorithm)接口
  9. * 数据表 table 的范围分片
  10. * @author Peng zhizhong
  11. * @version 1.0
  12. * fileName RangeShardingTableAlgorithm
  13. * createTime 2020/5/11 19:21
  14. */
  15. public class RangeShardingTableAlgorithm implements RangeShardingAlgorithm<Integer> {
  16. @Override
  17. public Collection<String> doSharding(final Collection<String> tableNames,
  18. final RangeShardingValue<Integer> shardingValue) {
  19. Set<String> result = new LinkedHashSet<>();
  20. // 如果between 2000000 and 7000000
  21. if (Range.closed(2000000,
  22. 7000000).encloses(shardingValue.getValueRange())) {
  23. for (String each : tableNames) {
  24. if (each.endsWith("0")) {
  25. result.add(each);
  26. }
  27. }
  28. } else {
  29. throw new UnsupportedOperationException();
  30. }
  31. return result;
  32. }
  33. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/756692
推荐阅读
相关标签
  

闽ICP备14008679号