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

embedded/2024/10/19 13:20:35/

文章目录

      • 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,返回参数就是需要查询的目标表列表。

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


http://www.ppmy.cn/embedded/93351.html

相关文章

Linux部署MySQL8.0

目录 一、部署前准备1.1、查看系统版本和位数&#xff08;32位或64位&#xff09;1.2、下载对应安装包 二、开始部署1、将安装包解压并且移动到目标安装目录2、准备MySQL数据和日志等存储文件夹3、准备MySQL配置文件 my.cnf4、创建mysql单独用户组和用户&#xff0c;将安装目录…

【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;数据结构 目录 前言 一、树 1.树的概念与结构 2.树的相关术语 3.树的表示方法 4.树型结构的实际应用场景 二、二叉树 1.二叉树的概念与结构 2.二叉树的…

在CentOS 7上安装Git的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 版本控制已经成为现代软件开发中不可或缺的工具。版本控制系统允许您在源代码级别跟踪软件。您可以跟踪更改、恢复到先前阶段&…

敏捷与DevOps有什么不同?

在软件开发领域&#xff0c;敏捷和DevOps因其对效率、协作和交付高质量产品的关注而受到欢迎。尽管它们有不同的目标&#xff0c;敏捷和DevOps常常被交替使用。本文旨在阐明这些方法之间的区别和共性&#xff0c;展示它们如何无缝协同以产生结果。 图源自Browser Stack 了解敏捷…

Java面试篇(线程池相关专题)

文章目录 1. 为什么要使用线程池2. 线程池的核心参数和线程池的执行原理2.1 线程池的核心参数2.2 线程池的执行原理 3. 线程池中常见的阻塞队列3.1 常见的阻塞队列3.2 ArrayBlockingQueue 和 LinkedBlockingQueue 的区别 4. 如何确定线程池的核心线程数4.1 应用程序中任务的类型…

利用python写一个可视化的界面

要利用Python编写一个可视化界面&#xff0c;你可以使用一些图形库来实现&#xff0c;例如Tkinter、PyQt、wxPython等。以下是一个使用Tkinter的示例代码&#xff1a; import tkinter as tk# 创建一个窗口对象 window tk.Tk()# 定义一个按钮点击事件的处理函数 def buttonCli…

Linux Vim教程

Linux Vim 教程 Vim&#xff08;Vi IMproved&#xff09;是一个强大的文本编辑器&#xff0c;广泛用于编程和系统管理。本文将带你全面了解 Vim 的基础使用、常用命令、高级功能等。 1. 安装 Vim 在大多数 Linux 发行版中&#xff0c;Vim 已经预装。如果没有&#xff0c;可以…

【项目】火灾烟雾检测管理系统。PyQT5+QT Designe+YOLOv8_ssod半监督算法+OpenCV

【项目】火灾烟雾检测管理系统。PyQT5QT DesigneYOLOv8_ssod半监督算法OpenCV 0.摘要1.引言2.烟雾检测算法2.0图像标注2.1 YOLOv8全监督算法结构2.2 Efficient-Teacher半监督算法结构 3.性能对比图4.源码、论文获取 0.摘要 火灾是常见而危险的自然灾害&#xff0c;不仅对人类生…