【经验分享】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,返回参数就是需要查询的目标表列表。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/396219.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VUE结合elementui实现分页器列表

<template><div>外贸知识<div class"art-box"><div class"art-item-box"><div class"art-item" v-for"(art, index) in paginatedArtList" :key"index"><a :href"art.artsrc"&g…

离开SD的大佬们另组战队,开源新品牌冲击MJ王座

FLUX.1强势登场&#xff0c;秒杀Midjourney&#xff1f; Midjourney 6.1 才发表几天&#xff0c;FLUX.1立刻就来踢馆了 离职四个月&#xff0c;Stability AI 核心成员 Robin Rombach 前几日官宣成立了 Black Forest Labs&#xff0c;公司推出的第一个产品 FLUX.1&#xff0c;…

GStreamer 简明教程(一):环境搭建,运行 Basic Tutorial 1 Hello world!

文章目录 前言一、源码环境搭建二、Basic Tutorial 1 Hello world三、开启更多日志参考 前言 本系列文章将纪录学习 [GStreamer] 的过程。 为什么想学习 [GStreamer]&#xff0c;有这么几个原因&#xff1a; 多媒体处理是一个复杂的任务&#xff0c;[GStreamer] 的管道架构可…

Docker最佳实践(七):安装MinIO文件服务器

大家好&#xff0c;欢迎各位工友。 Minio是一个开源免费的高性能对象存储服务器&#xff0c;专为大规模数据集和高并发访问而设计。它具有出色的读写性能和低延迟&#xff0c;可以满足对数据速度和效率要求较高的应用场景。本篇呢我们就来演示一下如何在Docker中搭建Minio容器&…

Java的线程实现

我们知道&#xff0c;线程是比进程更轻量级的调度执行单位&#xff0c;线程的引入&#xff0c;可以把一个进程的资源分配和执行调度分开&#xff0c;各个线程既可以共享进程资源&#xff08;内存地址、文件I/O等&#xff09;&#xff0c;又可以独立调度。目前线程是Java里面进行…

智能分析,安全无忧:AI视频分析技术在安全生产中的深度应用

在当今快速发展的科技时代&#xff0c;视频智能分析技术&#xff08;Intelligent Video Analysis&#xff0c;简称IV&#xff09;已经成为提升安全生产水平的重要手段。这一技术通过计算机图像视觉分析技术&#xff0c;实现了对场景中目标的自动识别和追踪&#xff0c;有效提升…

【层归一化用于单个样本适合于序列建模,通俗】

层归一化&#xff08;Layer Normalization&#xff09;&#xff0c;简称 LayerNorm&#xff0c;会将神经网络层的激活值规范到均值为0&#xff0c;并将其方差归一化为1。尤其是在循环神经网络&#xff08;RNNs&#xff09;和自注意力模型&#xff08;如 Transformers&#xff0…

【学习笔记】Day 8

写在开头&#xff1a; 最近老板突然提出一个全新的组会主题&#xff0c;是关于 “最近我犯的傻”&#xff0c;其目的在于提供乐子的同时引以为戒。本来我还在愁到底去哪里找干的啥事儿&#xff0c;结果今天直接拉了个大的。什么叫无心插柳柳成荫啊&#xff0c;悲。 一…

【C++进阶】红黑树

目录 什么是红黑树&#xff1f;红黑树红黑树的性质 定义红黑树红黑树的操作insertinorderfindheightsize构造函数析构函数赋值拷贝判断红黑树 全部代码总结 什么是红黑树&#xff1f; 红黑树 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉搜索树&#xff…

lora通信模块工作模式(半双工)

一&#xff0c;工作模式 1&#xff0c;透明模式 2&#xff0c;定点模式 3&#xff0c;广播模式 测试结果 1&#xff0c;定点模式下两个必须都是定点模式才能通信 2&#xff0c;广播模式可以发送到透明模式 3&#xff0c;定点模式发送不了透明模式

【Python第三方库】Requests全面解析

文章目录 安装基本用法测试网站发送GET请求发送POST请求更多请求请求参数请求头其他常用请求属性处理响应响应状态码响应内容 处理超时处理异常 requests 是一个非常流行的 Python HTTP 库&#xff0c;用于发送所有类型的 HTTP 请求。它简洁易用&#xff0c;能够处理复杂的请求…

数据结构——栈的讲解(超详细)

前言&#xff1a; 小编已经在前面讲完了链表和顺序表的内容&#xff0c;下面我们继续乘胜追击&#xff0c;开始另一个数据结构&#xff1a;栈的详解&#xff0c;下面跟上小编的脚步&#xff0c;开启今天的学习之路&#xff01; 目录 1.栈的概念和结构 1.1.栈的概念 1.2.栈的结构…

Vatee万腾平台:数据智能的创新引擎,引领企业数字化转型新纪元

在数字化转型的浪潮中&#xff0c;企业正以前所未有的速度重构着自身的运营模式与核心竞争力。作为这一变革的领航者&#xff0c;Vatee万腾平台凭借其卓越的数据智能能力&#xff0c;正逐步揭开企业数字化转型的新篇章。本文将深入探讨Vatee万腾平台如何以数据为核心&#xff0…

【多线程基础】进程和线程的区别和联系(重要)

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;Java多线程 &#x1f4da;本系列文章为个人…

【JavaEE】CAS原理

目录 ​前言 什么是CAS&#xff1f; 如何使用CAS&#xff1f; CAS实现自旋锁 CAS的ABA问题 面试题 1.讲解下你自己理解的CAS机制 2.ABA问题怎么解决&#xff1f; 前言 在多线程中&#xff0c;多个线程同时对一个共享变量进行读写操作&#xff0c;那么就会出现线程安全问…

01 NoSQL之Redis配置与优化

目录 1.1 Redis介绍 1.1.1关系数据库与非关系型数据库 1 . 关系型数据库 2. 非关系型数据库 3.非关系型数据库产生背景 (1) High performance--对数据库高并发读写需求 &#xff08;2) Huge Storage--对海量数据高效存储与访问需求 &#xff08;3) High Scalability …

gitlab cicd快速入门有哪些方法 gitlabcicd和Jenkins哪个更好用

在现代软件开发中&#xff0c;持续集成和持续交付&#xff08;CI/CD&#xff09;已成为必不可少的流程。它们不仅能提高开发效率&#xff0c;还能保证代码的质量和稳定性。在众多CI/CD工具中&#xff0c;GitLab和Jenkins是最为常用的两种。本文将围绕“gitlab ci/cd快速入门有哪…

vuex properties of undefined (reading ‘getters‘)

前言&#xff1a; 最近打算用vue 写个音乐播放器&#xff0c;在搞 vuex 的时候遇到一个很神奇报错&#xff1b;vuex 姿势练了千百次了&#xff0c;刚开始的时候我一直以为是代码问题&#xff0c;反复检查了带了&#xff0c;依旧报错。 Error in mounted hook: "TypeError:…

[Android] [解决]Bottom Navigation Views Activity工程带来的fragment顶部空白间距问题

用Android Stuio创建一个Bottom Navigation Views Activity工程&#xff0c; 我们刻意设置一下fragment背景为黑色&#xff0c;会发现&#xff0c;这个fragment离顶部还有一段不小空白距离&#xff0c; 怎么解决呢&#xff1f; 在activity_main.xml里面&#xff0c;删掉这句&a…

极狐GitLab安全版本:16.10.1、16.9.3、16.8.5

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…