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

使用ShardingSphere实现MySql的分库分表

目录

 

一 什么是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.kler.cn/a/302354.html

相关文章:

  • git没有识别出大写字母改成小写重命名的文件目录
  • SpringBoot参数注解
  • UDP协议和TCP协议之间有什么具体区别?
  • LabVIEW开发相机与显微镜自动对焦功能
  • 使用pdfjs加载多页pdf并实现打印
  • SAP_MM_SD_PP_FICO_视频课程几乎免费送
  • 洛谷 P3065 [USACO12DEC] First! G
  • Gitlab pre-receive hooks适配java p3c-pmd和python pycodestyle
  • Maven 深入指南:构建自动化与项目管理的艺术
  • 推动生态系统架构创新与可持续发展的关键引擎——The Open Group 2024年度大会全解析
  • Java使用Instant时输出的时间比预期少了八个小时
  • Linux数据相关-第3个服务-实时同步sersync
  • 828华为云征文 | 云服务器Flexus X实例:源码安装 Redis 实例测评
  • GPT撰写开题报告教程——课题确定及文献调研
  • ubuntu打包命令
  • SAP B1 单据页面自定义 - 用户界面编辑字段
  • 面试高阶问题:单片机选型策略万字长文详解
  • 关于GPT5训练失败的思考
  • CRM客户关系管理系统开发源码小程序
  • 【机器学习】参数学习的基本概念以及贝叶斯网络的参数学习和马尔可夫随机场的参数学习
  • FEDERATED引擎
  • 更改flutter 应用的应用名称和图标
  • PHP一键约课高效健身智能健身管理系统小程序源码
  • vue3打包 error in node_modules/@types/node/stream/web.d.ts 错误解决办法
  • Centos7安装MySql(特详细)
  • 栈的内容..