使用ShardingSphere实现MySql的分库分表

news2024/11/15 21:48:55

目录

 

一 什么是ShardingSphere分库分表

二 代码实现

1.导入相关依赖

2.配置相关参数

3.创建学生类以及mapper接口

4.实现 StandardShardingAlgorithm接口自定义分片算法


唐洋洋我知道你在看!!!嘿嘿

一 什么是ShardingSphere分库分表

我们平时在设计数据库的时候,一般都是一个数据库里面有很多张表,比如用户表,那么所有的用户信息都会存在这一张表里面。但是当数据量特别大的时候,如果你只用一个数据库一张用户表来存,这样就会到这这个数据库访问压力过大。所以分库分表就是,把大量用户数据分成多个数据库的多张表来存,这里以学生信息表为例:

7d2906c055de41f2a0f46dfda76f13d9.png

可以看到,我创建了两个数据库,每个数据库分别有两张表来存储学生信息,这样相当于一共有四张学生表了,这样就能减少每个数据库的访问压力。

既然分库分表的意思明白了,那么我们查询或者插入学生表的时候,该怎么操作呢?比如我现在要存入一个学生信息,我该往哪个表存呢?那么这里肯定是通过计算出来的,而且是某种算法,整体要平均。

所以这就是我们ShardingSphere的作用。

二 代码实现

1.导入相关依赖


        <!--        shardingsphere依赖-->


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core</artifactId>
            <version>5.3.2</version>
            <exclusions>
                <exclusion>
                    <artifactId>snakeyaml</artifactId>
                    <groupId>org.yaml</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 坑爹的版本冲突 -->
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.26</version>
        </dependency>

2.配置相关参数

application.yml参数:

9429aac9efec43a8956ac969f89f2fec.png

spring:
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:classpath:shardingsphere-config.yaml

 shardingsphere-config.yaml参数:

72bef31d8ce2452a836b92fe6b4c3ae4.png

dataSources:
  student_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://localhost:3306/student_0?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: 1234
  student_1:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://localhost:3306/student_1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: 1234
rules:
  - !SHARDING #分片规则
    tables:
      tb_student: #逻辑表名
        actualDataNodes: student_${0..1}.t_student_${0..3}
        databaseStrategy: # 分库策略
          standard: # 用于单分片键的标准分片场景
            shardingColumn: id # 分片列名称
            shardingAlgorithmName:  db_hash_mode_algorithm # 分片算法名称
        tableStrategy: # 分表策略,同分库策略
          standard: # 用于单分片键的标准分片场景
            shardingColumn: id # 分片列名称
            shardingAlgorithmName:  tb_student_hash_mode_algorithm # 分片算法名称
    # 分片算法配置
    shardingAlgorithms:
      db_hash_mode_algorithm:
        type: CLASS_BASED  # 分片算法类型  自定义
        props: # 分片算法属性配置
          db_sharding-count: 2
          table_sharding-count: 4
          strategy: standard #标准的分片算法
          algorithmClassName: com.feisi.shardingsphere.MyStandardShardingAlgorithm
      tb_student_hash_mode_algorithm:
        type: HASH_MOD
        props:
          sharding-count: 4
props:
  sql-show: true

3.创建学生类以及mapper接口

492f3f78e4db48d5a9d0877e092aa5e0.png

学生类:

package com.feisi.shardingsphere.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;
import org.springframework.stereotype.Component;

@Data
@TableName("tb_student")
@Builder
@Component
public class Student {
    @TableId(type = IdType.INPUT)
    private Long id;  //分片键
    private String name;
    private Integer age;
}

学生mapper接口:

package com.feisi.shardingsphere.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.feisi.shardingsphere.pojo.Student;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}

4.实现 StandardShardingAlgorithm接口自定义分片算法

package com.feisi.shardingsphere;

import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.sharding.algorithm.sharding.ShardingAutoTableAlgorithmUtil;
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 org.apache.shardingsphere.sharding.exception.algorithm.sharding.ShardingAlgorithmInitializationException;

import java.util.Collection;
import java.util.Optional;
import java.util.Properties;

public class MyStandardShardingAlgorithm implements StandardShardingAlgorithm<Comparable<?>> {


    // 数据库的数量配置参数名
    private static final String DB_SHARDING_COUNT_KEY = "db_sharding-count";
    // 表的数量配置参数名
    private static final String TABLE_SHARDING_COUNT_KEY = "table_sharding-count";
    private int dbShardingCount;
    private int tableShardingCount;

    @Override
    public void init(final Properties props) {
        dbShardingCount = getDbShardingCount(props);
        tableShardingCount = getTableShardingCount(props);
    }

    private int getTableShardingCount(Properties props) {
        ShardingSpherePreconditions.checkState(props.containsKey(TABLE_SHARDING_COUNT_KEY), () -> new ShardingAlgorithmInitializationException(getType(), "Sharding count cannot be null."));
        return Integer.parseInt(props.getProperty(TABLE_SHARDING_COUNT_KEY));
    }

    private int getDbShardingCount(Properties props) {
        ShardingSpherePreconditions.checkState(props.containsKey(DB_SHARDING_COUNT_KEY), () -> new ShardingAlgorithmInitializationException(getType(), "Sharding count cannot be null."));
        return Integer.parseInt(props.getProperty(DB_SHARDING_COUNT_KEY));
    }


    @Override
    //availableTargetNames: ds_${0..1}: ds_0  ds_1
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Comparable<?>> shardingValue) {
        //id进行hash    数据库数量 2   表的数量 4
//        这里使用哈希取余的算法
        // hash % 4 = 0..3 /2   0,1 /2 = 0   2,3/2 = 1
        String suffix = String.valueOf(hashShardingValue(shardingValue.getValue()) % tableShardingCount / dbShardingCount);
        return ShardingAutoTableAlgorithmUtil.findMatchedTargetName(availableTargetNames, suffix, shardingValue.getDataNodeInfo()).orElse(null);
    }

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Comparable<?>> shardingValue) {
        return availableTargetNames;
    }
    //对分片键的值进行hash算法
    private long hashShardingValue(final Object shardingValue) {

        return Math.abs((long) shardingValue.hashCode());
    }

    @Override
    public String getType() {
        return "CLASS_BASED";
    }

}

这里自定义分片算法在dosharding方法里面,分片算法的意思就是,根据你的分片建通过算法确定你的学生信息存储到哪个数据库中的哪张表里面去。

这里使用的是哈希取余算法,先根据你的分片键(这里的分片键就是id),计算出它的哈希值,然后:

        哈希值%你的数据表的数量=要存的哪块表

        要存的哪块表%你的数据库的数量=要存在哪个库里面。

为什么公式是这样的,因为我们的每个库从0开始,每个库对应下面的表也是从0开始。所以这个公式就能算出来。

比如一个id的哈希值是:448488114

我们的库数量是2个(0,1)

表数量是4个(0,1,2,3)

那么:448488114%4=2(存在表2里面)

但是表2在数据库1下面,所以你的算法不能算错,如果算到0库,那么就找不到这个张表了。

2/2=1(数据库1)

这样就完成了,最后算到你这个学生信息应该存到数据库1下面的数据表2中。

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Servlet入门学习笔记-Servlet技术

为什么需要Servlet &#xff1f; 使用JSP技术如何编写服务器动态网页&#xff1f; 流程图&#xff1a;JSP使用Java生成动态内容 在JSP技术出现之前如何编写服务器动态网页&#xff1f; 流程图&#xff1a;Java代码就是Servlet程序 什么是Servlet &#xff1f; Servlet 是一个…

sqli-labs靶场自动化利用工具——第10关

文章目录 概要整体架构流程技术细节执行效果小结 概要 Sqli-Labs靶场对于网安专业的学生或正在学习网安的朋友来说并不陌生&#xff0c;或者说已经很熟悉。那有没有朋友想过自己开发一个测试脚本能实现自动化化测试sqli-labs呢&#xff1f;可能有些人会说不是有sqlmap&#…

YoloV10改进策略:Block改进|PromptIR(NIPS‘2023)|轻量高效,即插即用|(适用于分类、分割、检测等多种场景)

文章目录 摘要代码详解如何在自己的论文中描述摘要 本文使用PromptIR框架中的PGM模块来改进YoloV10。PGM(Prompt Generation Module)模块是PromptIR框架中的一个重要组成部分,主要负责生成输入条件化的提示(prompts)。这些提示是一组可学习的参数,它们与输入特征相互作用…

【Java】方法的重载

文章目录 前言一、方法重载是什么&#xff1f;二、方法重载的注意事项 1、一个类中&#xff0c;只要一些方法的名称相同&#xff0c;形参列表不同&#xff0c;那么它们就是方法重载了&#xff0c;其他的不管&#xff08;如&#xff1a;修饰符&#xff0c;返回值类型是否一样都无…

彻底学会防抖和节流

目录 防抖&#xff08;Debounce&#xff09; 节流&#xff08;Throttle&#xff09; 如何选择使用防抖和节流&#xff1f; 总结 Vue 3 中使用防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09; 防抖&#xff08;Debounce&#xff09;示例 节…

普发Pfeiffer TCP600TCP5000手侧

普发Pfeiffer TCP600TCP5000手侧

unity3d入门教程三

unity3d入门教程三 8.1游戏脚本8.2脚本的使用8.3认识脚本组件8.4帧率9.1游戏脚本9.2获取节点和组件9.3MonoBehaviour9.4父节点与子节点9.5组件的属性9.6脚本的单步调试 8.1游戏脚本 通过程序控制对象属性&#xff08;如运动&#xff0c;修改transform的位置属性&#xff09; …

【STM32】VOFA+上位机 PID调参

【STM32】VOFA上位机 PID调参 前言VOFA简介 VOFA配置VOFA动态调节PID参数VOFA控件STM32解析数据包 PID参数整定一般调节法临界比例法试凑法 前言 参考文章如下&#xff1a;VOFA使用说明 使用VOFA上位机进行PID调参 PID参数整定 VOFA VOFA是一款简单易上手的上位机调试软件&a…

vue之我不会

计算属性 例子&#xff1a; 注意&#xff1a;调用计算属性时&#xff0c;不可以带括号&#xff0c;那样调用的就是方法&#xff0c;如&#xff1a;以下调用fullName时不可funnName() <div id"root">姓&#xff1a;<input type"text" v-model"…

Go语言练习——语法实践

目录 一、数组 1.多维数组的声明和使用 2.数组与切片的转换 3.数组在函数中的使用 二、切片 1.切片的动态扩容机制 2.切片的复制与修改 3.切片在排序算法中的应用 三、结构体 1.结构体的嵌套与方法 2.结构体与JSON的序列化 3.结构体的工厂模式 四、映射 1.映射的并发访问 2.映射…

erlang学习: Mnesia Erlang数据库4

表的类型和位置 内存表 它们的速度非常快&#xff0c;但是里面的数据是易失的&#xff0c;所以如果机器崩溃或者你停止了DBMS&#xff0c;数据就会丢失。 磁盘表 磁盘表应该不会受到系统崩溃的影响&#xff08;前提是磁盘没有物理损坏&#xff09;。 当Mnesia事务写入一个表并…

Qt如何链接和使用第三方库详解

在开发Qt应用程序时&#xff0c;我们经常会遇到需要使用第三方库的情况。无论是为了实现特定的功能&#xff0c;还是为了提高开发效率&#xff0c;使用第三方库都是一个非常常见的做法。本文将详细介绍如何在Qt项目中链接和使用第三方库。 基本步骤 配置Qt项目 在Qt项目中使…

Java | Leetcode Java题解之第402题移掉K位数字

题目&#xff1a; 题解&#xff1a; class Solution {public String removeKdigits(String num, int k) {Deque<Character> deque new LinkedList<Character>();int length num.length();for (int i 0; i < length; i) {char digit num.charAt(i);while (!…

最新免费云服务器,有需要的自行领取

目前云服务器市场竞争很激烈&#xff0c;为了吸引用户上云&#xff0c;很多云服务器提供商都提供了相应的免费试用活动&#xff0c;这些活动旨在帮助用户体验其服务和产品。 以下是一些值得关注的最新免费云服务器资源及其特点&#xff1a; 一、雨云 活动地址&#xff1a;点此…

MBD_入门篇_24_SimulinkSources

24.SimulinkSources 24.1 概述 Source库里面是Simulink的产生或输入信号数据的模块&#xff0c;要么用于产生信号要么用于传递上层的信号进来要么接地。用来生成代码的模块并不是很多&#xff0c;大部分都是用来仿真的。 Source库里面的模块都只有输出&#xff0c;没有输入。…

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:下(人物动画)

上个博客我们做出了人物的动画机和人物移动跳跃&#xff0c;接下来我们要做出人物展现出来的动画了 我们接下来就要用到动画机了&#xff0c;双击我们的动画机&#xff0c;进入到这样的页面&#xff0c;我这是已经做好的页面&#xff0c;你们是没有这些箭头的 依次像我一样连接…

大数据安全之Kerberos

Kerberos 是一个网络身份验证协议&#xff0c;旨在提供强身份验证&#xff0c;尤其是在开放网络环境中。它最早由麻省理工学院&#xff08;MIT&#xff09;开发&#xff0c;用于在不安全的网络环境中安全地验证用户身份。Kerberos 协议的设计旨在防止窃听、重放攻击和网络中的其…

工作分享,中芯国际招聘,附送內推码

內推码&#xff0c;中芯国际 &#x1f4da;【简介】&#xff1a;中芯国际(证券代码:00981.HK/688981.SH)是世界领先的集成电路晶圆代工企业之一&#xff0c;也是中国大陆集成电路制造业领导者 【详情】&#xff1a;https://nuaa.91job.org.cn/sub-station/announcementDetail…

keras和tensorflow可用的一组版本

目录 keras版本&#xff1a;3.5.0tensorflow&#xff1a;2.17.0之前的错误导包现在的正确导包 keras版本&#xff1a;3.5.0 tensorflow&#xff1a;2.17.0 之前的错误导包 其实也不是说错误&#xff0c;就是因为文件位置不对&#xff0c;所以VSCode总是有黄色波浪线&#xff0…

pycharm安装opencv

一、下载 在terminal使用pip进行安装 命令为&#xff1a;pip install opencv-python 本身下载很慢&#xff0c;可以使用清华的镜像源 ​https://pypi.tuna.tsinghua.edu.cn/simple​​ 完整的命令如下&#xff1a; pip install opencv-python -i https://pypi.tuna.tsing…