Sharding-standard策略(四)
创始人
2024-05-29 03:13:01
0次

简介

参考代码工程(2-standard)

第三节使用springboot搭建sharding环境时候以最简单的inline策略为演示,发现inline只支持最简单的等于查询。对于范围查询不支持(表通常要结合时间最范围查询)

此时要引用标准分片策略(standard)

standard策略可以看到配置信息一共3个参数

#分片主键
sharding-column= 
# 精准分片算法-》指定我们实现类
precise-algorithm-class-name= 
# 范围查询算法-》指定我们实现类
range-algorithm-class-name= 

配置信息

使用yaml修改配置类成以下

#  单库分表 配置
spring:shardingsphere:datasource:# 配置数据库名称 相当于给数据源取别名(可以配置多个库,以逗号隔开)names: m1# 配置具体数据库连接信息m1:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.cj.jdbc.Driver# 配置 数据库 testurl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTCusername: rootpassword: 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..2}# 表策略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# 配置是否打印SQLprops:sql.show: true

精准分片算法(一)

创建一个包“com.wnn.sd.algorithm”,首先实现精准分片算法PreciseShardingAlgorithm,所谓精准分片算法,可以参考inline算法一样实现一个对订单表主键取摸2的算法

package com.wnn.sd.algorithm;import java.math.BigInteger;
import java.util.Collection;import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;import lombok.extern.slf4j.Slf4j;/*** @Description: 精确匹配查询,需要实现PreciseShardingAlgorithm,可以实现对 `=`以及`in`的查询**/
@Slf4j
public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm {/*** 精确匹配查询** @param tbNames*            数据库中所有的事实表* @param shardingValue*            分片相关信息* @return 返回匹配的数据源*/@Overridepublic String doSharding(Collection tbNames, PreciseShardingValue shardingValue) {// 获取-打印逻辑表String logicTableName = shardingValue.getLogicTableName();log.info("logicTableName = {}", logicTableName);// 主键值转换BigInteger做计算BigInteger orderId = BigInteger.valueOf(shardingValue.getValue());// 取摸算法%2+1BigInteger tabelNuber = (orderId.mod(new BigInteger("2"))).add(new BigInteger("1"));// 打印实际路由后的表String actTableName = logicTableName + "_" + tabelNuber;log.info("actTableName= {}", actTableName);// 判断算法的结果是否在数据库实际表列表中if (tbNames.contains(logicTableName + "_" + tabelNuber)) {return actTableName;}throw new RuntimeException("表不存在");}
}

把t_order_1和t_order_2清除,使用Test类的add()方法(参考上一节Test类)给数据库添加10条数据,结果保持和inline一致。

    /*** 添加数据*/@Testpublic void addOrder() {for (int i = 0; i < 10; i++) {Order order = new Order();order.setOrderName("wn" + i);orderMapper.insert(order);}}/*** 等于查询 ID基于表2*/@Testpublic void queryByEQ() {List orders =orderMapper.selectList(new LambdaQueryWrapper().eq(Order::getOrderId, 1629805480188895233L));orders.forEach(o -> System.out.println(o));}

可以看到插入日志中输出了@Slf4j 下 log.info()信息,说明新数据,sharding能够根据我们的配置信息,加载我们实现的算法类

add()

2023-03-05 15:06:52.819  INFO 23220 --- [           main] c.w.s.a.MyPreciseShardingAlgorithm       : logicTableName = t_order
2023-03-05 15:06:52.819  INFO 23220 --- [           main] c.w.s.a.MyPreciseShardingAlgorithm       : actTableName= t_order_2

queryByEQ() ,路由查询结果正确

2023-03-05 15:09:47.354  INFO 35236 --- [           main] c.w.s.a.MyPreciseShardingAlgorithm       : logicTableName = t_order
2023-03-05 15:09:47.355  INFO 35236 --- [           main] c.w.s.a.MyPreciseShardingAlgorithm       : actTableName= t_order_2
2023-03-05 15:09:47.374  INFO 35236 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT  order_id,2023-03-05 15:09:47.375  INFO 35236 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: SELECT  order_id,order_name,order_type,order_desc,create_user_id,create_user_name,create_time  FROM t_order_2 WHERE (order_id = ?) ::: [1629805480188895233]

范围分片算法(二)

再实现范围查询算法MyRangeShardingAlgorithm类,该类实现RangeShardingAlgorithm类,此时从方法shardingValue中拿到SQL语句中between的上限和下限值,因为没有具体业务分片算法暂时列为//TODO,返回结果为全表(一共2张表)测试通过RangeShardingAlgorithm实现类doSharding()方法是否能够执行between查询

package com.wnn.sd.algorithm;import java.util.Arrays;
import java.util.Collection;import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;import lombok.extern.slf4j.Slf4j;/*** 实现范围查询逻辑**/
@Slf4j
public class MyRangeShardingAlgorithm implements RangeShardingAlgorithm {@Overridepublic Collection doSharding(Collection availableTargetNames,RangeShardingValue shardingValue) {Long upperValue = shardingValue.getValueRange().upperEndpoint();// 上限Long lowerValue = shardingValue.getValueRange().lowerEndpoint();// 下限//TODOString logicTableName = shardingValue.getLogicTableName();log.info("MyRangeShardingAlgorithm +  logicTableName {}", logicTableName);return Arrays.asList(logicTableName + "_1", logicTableName + "_2");}
}

可以看到打印输出结果,不像使用inline那样报错,而是通过MyRangeShardingAlgorithm算法返回的表名执行SQL

2023-03-05 15:25:48.009  WARN 12852 --- [           main] c.b.m.c.t.support.ReflectLambdaMeta      : Unable to make field private final java.lang.Class java.lang.invoke.SerializedLambda.capturingClass accessible: module java.base does not "opens java.lang.invoke" to unnamed module @3d012ddd
2023-03-05 15:25:48.387  INFO 12852 --- [           main] c.w.s.a.MyRangeShardingAlgorithm         : MyRangeShardingAlgorithm +  logicTableName t_order2023-03-05 15:25:48.418  INFO 12852 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: SELECT  order_id,order_name,order_type,order_desc,create_user_id,create_user_name,create_time  FROM t_order_1 WHERE (order_id BETWEEN ? AND ?) ::: [1629805480188895233, 1629805480214061057]
2023-03-05 15:25:48.418  INFO 12852 --- [           main] ShardingSphere-SQL                       : Actual SQL: m1 ::: SELECT  order_id,order_name,order_type,order_desc,create_user_id,create_user_name,create_time  FROM t_order_2 WHERE (order_id BETWEEN ? AND ?) ::: [1629805480188895233, 1629805480214061057]

结论

由此可见standard标准分片算法,实现相比inline繁杂一点。一般使用standard策略是为了搭配范围分片算法使用。

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...