当前位置: 首页 > news >正文

【经验分享】ShardingSphere+Springboot-04:自定义分片算法(COMPLEX/STANDARD)

文章目录

      • 3.4 CLASS_BASED 自定义类分片算法
        • 3.4.1 复杂分片自定义算法(strategy=COMPLEX )
        • 3.4.2 STANDARD 标准分片自定义算法
        • ## 进阶:star: 自定义算法+范围查询优化

3.4 CLASS_BASED 自定义类分片算法

3.4.1 复杂分片自定义算法(strategy=COMPLEX )

通过配置分片策略类型和算法类名,实现自定义扩展。 掌握自定义类算法就算法完全掌握了分片算法的精髓,可以根据业务需求灵活配置分片规则。

类型:CLASS_BASED

可配置属性:

属性名称数据类型说明
strategyString分片策略类型,支持 STANDARD、COMPLEX 或 HINT(不区分大小写)
algorithmClassNameString分片算法全限定名

官方文档给出了一个参考案例如下,没有太多的说明,这尝试用自定义分片算法重新实现[3.3.1]中的行表达式分表规则

package org.apache.shardingsphere.sharding.fixture;import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;import java.util.Collection;public final class ClassBasedStandardShardingAlgorithmFixture implements StandardShardingAlgorithm<Integer> {@Override
public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Integer> shardingValue) {for (String each : availableTargetNames) {if (each.endsWith(String.valueOf(shardingValue.getValue() % 4))) {return each;}}return null;
}@Override
public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Integer> shardingValue) {return availableTargetNames;
}
}

实现目标:根据用户类型user_type和部门dep_id进行复杂分库分表

编写分片算法类:

  1. 根据分片策略类型( STANDARD、COMPLEX 或 HINT)实现对应的算法接口,这里需要用到的复杂算法的接口

    image-20240809111027491

  2. 实现必须的方法,这里核心关注doSharding方法,编写思路记录如下

    • 获取列名和分片值的映射(必备的,获取了才能根据分片键值计算数据源嘛
    • (可选)获取逻辑表名、范围值映射
    • 获取分片键值,并计算得到真实数据源

完整算法类:

package com.zhc.shard.algo;import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingValue;import java.util.*;/*** @Author zhuhuacong* @Date: 2024/08/09/ 11:07* @description*/
@Slf4j
public class UserTypeDepIdAlgorithm implements ComplexKeysShardingAlgorithm<String> {// 定义列名常量private static final String col1 = "user_type";private static final String col2 = "dep_id";/*** 实现分片逻辑* 当分片条件存在时,根据给定的分片键计算出特定的数据源* 如果无法计算出合适的分片结果,则抛出异常** @param collection               数据源集合(这里是分表策略,所以这里是真实表集合* @param complexKeysShardingValue 分片条件对象* @return 分片后的数据源名称列表* @throws RuntimeException 当无法得到合适的分片结果时*/@Overridepublic Collection<String> doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {// 获取逻辑表名String logicTableName = complexKeysShardingValue.getLogicTableName();// 获取列名和分片值的映射Map columnNameAndShardingValuesMap = complexKeysShardingValue.getColumnNameAndShardingValuesMap();// 获取列名和范围值的映射(未用到)Map columnNameAndRangeValuesMap = complexKeysShardingValue.getColumnNameAndRangeValuesMap();// 获取分片键值List c1UserType = (List) columnNameAndShardingValuesMap.get(col1);List c2DepId = (List) columnNameAndShardingValuesMap.get(col2);// 如果任一分片键存在,则进行分片计算if (Optional.ofNullable(c1UserType).isPresent() || Optional.ofNullable(c2DepId).isPresent()) {// 【算法核心】 根据分片键值计算数据源索引long userType = c1UserType.get(0) != null ? Long.parseLong(c1UserType.get(0).toString()) : 0;long depId = c2DepId.get(0) != null ? Long.parseLong(c2DepId.get(0).toString()) : 0;long shardingId = ((userType + depId) % 2);String tableName = logicTableName + "_" + shardingId;log.info("userType:{};shardingId:{};余数{};真是表名{}", userType, depId, shardingId , tableName);// 返回计算后的数据源名称return Collections.singletonList(tableName);}// 如果无法得到合适的分片结果,则记录日志并抛出异常log.info("没有得到合适的分片结果=:表名{},参数:{}", collection, columnNameAndShardingValuesMap);throw new RuntimeException("没有得到合适的分片结果");}@Overridepublic Properties getProps() {return null;}@Overridepublic void init(Properties properties) {}
}

进行测试

分表策略运行正确

image-20240809114449222

3.4.2 STANDARD 标准分片自定义算法

快速实现,表结构还是参考前面的打卡表。要求根据早中晚三个时段的打卡时间进行分表,分别存入

stu_clock_am、stu_clock_noon、stu_clock_eve;

yaml配置如下

spring:shardingsphere:rules:sharding:tables:# 打卡表stu_clock:actual-data-nodes: dsmain.stu_clock_am,dsmain.stu_clock_noon,dsmain.stu_clock_evekey-generate-strategy:column: idkey-generator-name: snowflaketable-strategy:standard:sharding-column: clockin_timesharding-algorithm-name: stu_clock_class_algo# 配置分片算法sharding-algorithms:stu_clock_class_algo:type: CLASS_BASEDprops:#分片策略类型,支持 STANDARD、COMPLEX 或 HINT(不区分大小写)strategy: STANDARD# 分片算法全限定名algorithmClassName: com.zhc.shard.algo.StuClockClassAlgorithm

算法代码

package com.zhc.shard.algo;import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Properties;/*** @Author zhuhuacong* @Date: 2024/08/09/ 14:56* @description StuClockClassAlgorithm*/
@Slf4j
public class StuClockClassAlgorithm implements StandardShardingAlgorithm<Date> {@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {String logicTableName = shardingValue.getLogicTableName();Date date = shardingValue.getValue();LocalDateTime localDateTime = DateUtil.toLocalDateTime(date);int hour = localDateTime.getHour();log.info("logicTableName: {} value: {} hour {}", logicTableName, date, hour);String actualTableName =null;if (hour > 15){actualTableName =  logicTableName + "_eve";} else if (hour > 10 ){actualTableName =  logicTableName + "_noon";} else {actualTableName =  logicTableName + "_am";}if (availableTargetNames.contains(actualTableName)){return actualTableName;}// 如果无法得到合适的分片结果,则记录日志并抛出异常log.info("没有得到合适的分片结果:表名{},参数:{}", shardingValue, shardingValue);throw new RuntimeException("没有得到合适的分片结果");}@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> shardingValue) {return availableTargetNames;}@Overridepublic Properties getProps() {return null;}@Overridepublic void init(Properties properties) {}
}

结果测试,

生成随机打卡时间,观察是否正确入库

image-20240809153044358

结果符合预期

## 进阶⭐️ 自定义算法+范围查询优化

可以发现,StandardShardingAlgorithm接口还有一个同样叫doSharding的接口,

    /*** Sharding.** @param availableTargetNames available data sources or table names* @param shardingValue sharding value* @return sharding results for data sources or table names*/Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<T> shardingValue);

传入的参数是一个带有范围(上下界限)shardingValue,一个是可用的真实表集合availableTargetNames,返回参数就是需要查询的目标表列表。

只要根据实际业务逻辑实现方法体内容即可。

相关文章:

【经验分享】ShardingSphere+Springboot-04:自定义分片算法(COMPLEX/STANDARD)

文章目录 3.4 CLASS_BASED 自定义类分片算法3.4.1 复杂分片自定义算法&#xff08;strategyCOMPLEX &#xff09;3.4.2 STANDARD 标准分片自定义算法## 进阶:star: 自定义算法范围查询优化 3.4 CLASS_BASED 自定义类分片算法 3.4.1 复杂分片自定义算法&#xff08;strategyCOM…...

如何设置RabbitMQ和Redis消息队列系统

设置RabbitMQ和Redis作为消息队列系统时&#xff0c;需要分别进行安装、配置和测试&#xff0c;以确保它们能够正常工作并满足你的应用需求。以下是一个基于这两个系统的设置指南&#xff1a; RabbitMQ的设置 1. 安装Erlang 由于RabbitMQ是用Erlang语言编写的&#xff0c;因…...

白骑士的Matlab教学高级篇 3.3 工具箱与扩展

MATLAB 提供了丰富的工具箱&#xff08;Toolbox&#xff09;和扩展功能&#xff0c;这些工具箱涵盖了各个领域的专业计算需求&#xff0c;如信号处理、图像处理、统计与机器学习等。利用工具箱&#xff0c;用户可以快速实现复杂的计算和分析任务。本文将介绍常用的工具箱及其使…...

bug: 配置flyway.locations多个脚本位置不生效

文章目录 业务场景场景一场景二 业务场景 随着项目版本迭代&#xff0c;数据库结构也会变动。如果一个项目引用其他项目的jar包&#xff0c;并且需要执行对应jar包的flyway脚本&#xff0c;就需要配置flyway.locations 场景一 正常情况下&#xff0c;在一个项目中可以在yml文件…...

8月5日SpringBoot学习笔记

今日内容:搭建mybatis ORM 配置数据源 $#的区别 增删改查 搭建mybatis 在原有maven项目基础配置上进行&#xff1a; pom文件添加依赖 <!-- Mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-…...

Java学习笔记(二十):反射、动态代理、日志、类加载器、xml、单元测试Junit、注解

目录 一、反射 1.1 反射的概述&#xff1a; 1.2 学习反射到底学什么&#xff1f; 1.3 获取字节码文件对象的三种方式 1.4 字节码文件和字节码文件对象 1.5 获取构造方法 1.6 获取构造方法并创建对象 1.7 获取成员变量 1.8 获取成员变量并获取值和修改值 1.9 获取成员…...

如何快速从文本中找到需要的信息,字典和正则灵活运用

import re #打开文本文件 f open("stock_data.txt",encoding"utf-8") #单独读取第一行数据处理进行分割&#xff0c;末尾换行符去掉 headers f.readline().strip().split(,) print(headers) #定义一个字典&#xff0c;以股标代码做为KEY,每个行做为值 st…...

springboot3整合redis

来源于https://www.bilibili.com/video/BV1UC41187PR/?spm_id_from333.1007.top_right_bar_window_history.content.click&vd_source865f32e12aef524afb83863069b036aa 一、整合redis 1.创建项目文件 2.添加依赖 <dependencies><dependency><groupId>…...

VUE基础快速入门

VUE 和 VUE-Cli VUE 是一种流行的渐进式JavaScript框架&#xff0c;用于构建Web用户界面它具有易学、轻量级、灵活性强、高效率等特点&#xff0c;并且可以与其他库和项目集成是目前最流行的前端框架之一VUE-Cli 称为“VUE脚手架”,它是由VUE官方提供的客户端&#xff0c;专门为…...

用Python实现特征工程之特征提取——数值特征提取、类别特征提取、文本特征提取、时间特征提取

特征提取是特征工程中的关键步骤&#xff0c;它从原始数据中提取有意义的特征&#xff0c;以便机器学习模型能够更好地理解和学习数据。根据数据类型&#xff0c;特征提取可以分为数值特征提取、类别特征提取、文本特征提取和时间特征提取。下面详细讲解每种特征提取方法&#…...

按图搜索新体验:阿里巴巴拍立淘API返回值详解

阿里巴巴拍立淘API是一项基于图片搜索的商品搜索服务&#xff0c;它允许用户通过上传商品图片&#xff0c;系统自动识别图片中的商品信息&#xff0c;并返回与之相关的搜索结果。以下是对阿里巴巴拍立淘API返回值的详细解析&#xff1a; 一、主要返回值内容 商品信息 商品列表…...

vue跨域问题

本地调试 可以通过在vue.config.js中配置devServer来实现跨域请求。 module.exports {publicPath: ./,productionSourceMap: false, // 生产环境是否生成 sourceMap 文件devServer: {proxy: {/bi: {target: http://1.11.113.20:1234/bi, // 后台接口域名ws: false, //…...

【NLP】文本处理的基本方法【jieba分词、命名实体、词性标注】

文章目录 1、本章目标2、什么是分词3、jieba的使用3.1、精确模式分词3.2、全模式分词3.3、搜索引擎模式分词3.4、中文繁体分词3.5、使用用户自定义词典 4、什么是命名实体识别5、什么是词性标注6、小结7、jieba词性对照表⭐ &#x1f343;作者介绍&#xff1a;双非本科大三网络…...

unity 本地使用Json(全套)

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、Json是什么&#xff1f;二、创建Json文件1.在线编辑并转实体类&#xff08;C#&#xff09;2.Json文件 三、解析Json并使用四、报错&#xff1a;JsonError&#xff1a;JsonExce…...

java消息队列ActiveMQ

安装 前置条件 activemq的运行依赖于jdk&#xff0c;需要提前安装jdk如果已经安装了jdk&#xff0c;需要根据jdk的版本来选择对应的版本进行安装activemq版本对应在官网上&#xff0c;使用java -version 看jdk的版本注意&#xff1a;jdk和mq的版本不一致会报错&#xff0c;电脑…...

Android SurfaceFlinger——信号同步原理(五十一)

经过前面系列文章的学习,我们的已经理解了 SurfaceFlinger 运行机制以及同步机制,但是SurfaceFlinger 又是以什么方法是把需要刷新的信号发送给 App 进程的。 一、VSync简介 垂直同步(Vertical Synchronization,简称 VSync)是一种用于同步视频信号和显示设备刷新率的技术…...

html+css网页制作 博云丝网5个页面 无js ui还原度100%

htmlcss网页制作 博云丝网5个页面 无js ui还原度100% 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取…...

Docker Hub 镜像代理加速

因为未知原因&#xff0c;docker hub 已经不能正常拉取镜像&#xff0c;可以使用以下代理服务来进行&#xff1a; "https://docker.m.daocloud.io", "https://noohub.ru", "https://huecker.io", "https://dockerhub.timeweb.cloud"…...

矩阵:消除冗余

矩阵 基本概念 矩阵&#xff08;Matrix&#xff09;是一个按照行和列排列的元素的二维数组。具体来说&#xff0c;一个 ( m \times n ) 的矩阵有 ( m ) 行和 ( n ) 列&#xff0c;表示为&#xff1a; A ( a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a m 1 a m 2 ⋯…...

【AWS账号解绑关联】Linker账号解绑重新关联注意事项

文章目录 一、来自客户疑问二、提交工单获取帮助三、最佳操作说明四、最佳操作步骤五、参考资料活动上新 一、来自客户疑问 将Linker账号&#xff0c;从一个组织中退出&#xff0c;重新关联到新的组织中&#xff0c;这解绑到重新完成新的关联绑定期间会在Linker账号中的账单中…...

用通俗的话解释下MCP是个啥?

在AI领域&#xff0c;模型的开发、部署和迭代速度日益加快&#xff0c;但随之而来的挑战也愈发显著&#xff1a;如何高效管理不同版本的模型&#xff1f;如何在复杂环境中确保模型的可追溯性和可复用性&#xff1f;如何实现跨团队、跨平台的模型协作&#xff1f; 在计算机领域…...

学习笔记(23): 机器学习之数据预处理Pandas和转换成张量格式[1]

学习笔记(23): 机器学习之数据预处理Pandas和转换成张量格式[1] 学习机器学习&#xff0c;需要学习如何预处理原始数据&#xff0c;这里用到pandas&#xff0c;将原始数据转换为张量格式的数据。 1、安装pandas pip install pandas 2、写入和读取数据 >>创建一个人工…...

12-Oracle 23ai Vector 使用ONNX模型生成向量嵌入

一、Oracle 23ai Vector Embeddings 核心概念​ 向量嵌入&#xff08;Vector Embeddings&#xff09;​​ -- 将非结构化数据&#xff08;文本/图像&#xff09;转换为数值向量 - - 捕获数据的语义含义而非原始内容 - 示例&#xff1a;"数据库" → [0.24, -0.78, 0.5…...

Go 语言 := 运算符详解(短变量声明)

Go 语言 : 运算符详解&#xff08;短变量声明&#xff09; : 是 Go 语言中特有的​​短变量声明运算符​​&#xff08;short variable declaration&#xff09;&#xff0c;它提供了简洁的声明并初始化变量的方式。这是 Go 语言中常用且强大的特性之一。 基本语法和用途 va…...

K7 系列各种PCIE IP核的对比

上面三个IP 有什么区别&#xff0c;什么时候用呢&#xff1f; 7 series Integrated Block for PCIE AXI Memory Mapped to PCI Express DMA subsystem for PCI Express 特点 这是 Kintex-7 内置的 硬核 PCIe 模块。部分事务层也集成在里面&#xff0c;使用标准的PCIE 基本没…...

LLM 笔记:Speculative Decoding 投机采样

1 基本介绍 投机采样&#xff08;Speculative Sampling&#xff09;是一种并行预测多个可能输出&#xff0c;然后快速验证并采纳正确部分的加速策略 在不牺牲输出质量的前提下&#xff0c;减少语言模型生成 token 所需的时间 传统的语言模型生成是 串行 的 必须生成一个&…...

[面试精选] 0104. 二叉树的最大深度

文章目录 1. 题目链接2. 题目描述3. 题目示例4. 解题思路5. 题解代码6. 复杂度分析 1. 题目链接 104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 2. 题目描述 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点…...

Kafka 单机部署启动教程(适用于 Spark + Hadoop 环境)

&#x1f9ed; Kafka 单机部署启动教程&#xff08;适用于 Spark Hadoop 环境&#xff09; &#x1f4e6; 一、Kafka 版本选择 推荐使用 Kafka 2.13-2.8.1&#xff08;Scala 2.13&#xff0c;稳定适配 Spark 3.1.2 和 Hadoop 3.1.1&#xff09; 下载地址&#xff08;Apache 官…...

Fetch与Axios:区别、联系、优缺点及使用差异

Fetch与Axios&#xff1a;区别、联系、优缺点及使用差异 文章目录 Fetch与Axios&#xff1a;区别、联系、优缺点及使用差异一、联系二、区别1. 浏览器支持与兼容性2. 响应处理3. 请求拦截和响应拦截4. 错误处理 三、优缺点1. Fetch API优点缺点 2. Axios优点缺点 四、使用上的差…...

[BIOS]VSCode zx-6000 编译问题

前提&#xff1a;Python 3.6.6及以上版本安装成功&#xff0c;Python 3.6.6路径加到了环境变量# DEVITS工具包准备好 问题&#xff1a;添加环境变量 1&#xff1a;出现环境变量错误&#xff0c;“py -3” is not installed or added to environment variables #先在C:\Windows里…...