SpringBoot集成Sharding-JDBC实现分库分表

news2024/11/14 20:39:45
本文已收录于专栏
《中间件合集》

目录

  • 版本介绍
  • 背景介绍
  • 拆分方式
  • 集成并测试
    • 1.引入依赖
    • 2.创建库和表
    • 3.pom文件配置
    • 3.编写测试类
      • Entity层
      • Mapper接口
      • MapperXML文件
      • 测试类
    • 4.运行结果
  • 自定义分片规则
    • 定义分片类
    • 编写pom文件
  • 总结提升

版本介绍

  SpringBoot的版本是: 2.3.12
  ShardingSphere-jdbc的版本是:5.1.2
  Mysql-Connector的版本是:8.0.19
  Druid的版本是:1.2.8

背景介绍

  分库分表是数据库设计中的一种常见策略,主要用于解决在高并发、大数据量场景下的性能瓶颈和管理问题。本文章采用Sharding-JDBC以水平分配的方式来实现分库分表。
ShardingSphere官网:https://shardingsphere.apache.org/document/5.1.2/cn/overview/
分库分表的原因:

  1. 性能提升:单一数据库在高并发情况下容易发生性能瓶颈,分库分表可以将请求分散到多个数据库或表上,降低单个数据库的压力。
  2. 容量管理:随着数据量的增长,单个数据库的存储能力可能不足。分库分表可以将数据分散到多个数据库中,以支撑更大的数据存储需求。
  3. 效率提升:在查询时,分表可以将查询范围缩小,只需要访问更少的数据,从而提高查询效率。
  4. 可维护性:分库分表可以更方便地进行数据备份、恢复和维护,提高系统的整体可维护性。
  5. 横向扩展:分库分表支持横向扩展,允许在现有架构中增加更多的数据库服务器,以适应业务增长。

拆分方式

1. 分库
  垂直分库:将不同功能模块或业务逻辑的数据存储在不同的数据库中。例如,用户数据和订单数据分别存放在不同的数据库中。
  水平分库:类似于分表,但是将同一类型的数据分散到不同的数据库中。例如,将用户数据按ID范围分散到不同的数据库。
2. 分表
  按范围分表:根据某个字段(如时间、ID等)的范围,将数据划分到不同的表中,每个表存储特定范围的数据。
  按哈希分表:对某个字段(如用户ID)进行哈希运算,根据哈希值将数据分配到不同的表中。

集成并测试

1.引入依赖


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>
        
        <!-- Database Driver -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.1.2</version>
        </dependency>

2.创建库和表

在这里插入图片描述
  在每个数据库中都需要创建多个相同的表,例如order_info_0、order_info_2、order_info_3等等,这样在配置分片规则的时候才会根据不同的计算方式映射到不同的库和表里面。

3.pom文件配置

server:
  port: 8081
spring:
  autoconfigure: # 排除druid 否则报错
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
  shardingsphere:
    # 开启sql打印
    enabled: true
    props:
      # 是否显示sql
      sql-show: true
    datasource:
      #数据源名称
      names: sharding0,sharding1
      #数据源实例: 如果这里还有master
      sharding0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class: com.mysql.cj.jdbc.Driver
        #使用Druid,不能使用jdbc-url 得使用url
        url: jdbc:mysql://localhost:3307/budget-lim-dev?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
      sharding1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/budget-lim-dev?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
    #分片规则
    rules:
      sharding:
        #对表进行分片
        tables:
          #逻辑表名,代表的是需要分表的名称
          order_info:
            #实际节点:这里代表的是 会使用sharding数据源中 order_info表 细分为0~3 4个表
            actual-data-nodes: sharding$->{0..1}.order_info_$->{0..1}
            #库策略
            database-strategy:
              standard:
                #根据num来进行分库
                sharding-column: num
                sharding-algorithm-name: alg_round-robin
            #表策略
            table-strategy:
              #标准表策略
              standard:
                #分表的列
                sharding-column: id
                #分片算法名称: 来源于下面的sharding-algorithms
                sharding-algorithm-name: alg_random
            key-generate-strategy: # 主键生成策略
              column: id  # 主键列
              key-generator-name: snowflake  # 策略算法名称(推荐使用雪花算法)
        #主键生成规则,SNOWFLAKE 雪花算法
        key-generators:
          snowflake:
            type: SNOWFLAKE
        #分片算法
        sharding-algorithms:
          alg_hash_mod:
            #类型:hash取余  类似于获取一个列的数
            type: HASH_MOD
            #分片的数量,因为是2个表,所以是2
            props:
              sharding-count: 2

mybatis:
  #映射文件 配置之后,mybatis会去扫描该路径下的xml文件,才会与Mapper对应起来
  mapper-locations: classpath:mapper/*.xml
  #别名类(实体类)所在包
  type-aliases-package: com.wzil.simplesharding.entity
  configuration:
    #驼峰转换
    map-underscore-to-camel-case: true

3.编写测试类

Entity层

/**
 * @Author: wzil
 * @DATE: 2024年7月24日
 * @Description:
 **/
@Data
public class OrderInfo {
    private Long id;
    private String name;
    private Integer num;
    private Date createTime;
}

Mapper接口

/**
 * @Author: wzil
 * @DATE: 2024年7月24日15:26:30
 * @Description: 创建mapper接口,
 **/

@Mapper
public interface OrderInfoMapper {

    List<OrderInfo> list();

    void save(OrderInfo orderInfo);

    void deleteById(@Param("id") Long id);

    void updateNameById(@Param("id") Long id, @Param("name") String name);

    OrderInfo getById(@Param("id") Long id);

    List<OrderInfo> limitOrder();

    List<OrderInfo> limitOrderWithOffset();

}

MapperXML文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:命名空间,用来映射对应的mapper
相当于将mapper和mapper.xml连接起来,这一步很重要-->
<mapper namespace="com.wzil.simplesharding.mapper.OrderInfoMapper">
    <insert id="save">
        insert into order_info(`name`,num,create_time) values(#{name},#{num},#{createTime})
    </insert>
    <update id="updateNameById">
        update order_info set name=#{name}
        where id=#{id}
    </update>
    <delete id="deleteById">
        delete from order_info where id=#{id}
    </delete>
    
    <select id="list" resultType="com.wzil.simplesharding.entity.OrderInfo">
        select * from order_info
    </select>
    <select id="getById" resultType="com.wzil.simplesharding.entity.OrderInfo">
        select * from order_info
        where id=#{id}
    </select>
    <select id="limitOrder" resultType="com.wzil.simplesharding.entity.OrderInfo">
        select * from order_info
        order by num desc
        limit 10
    </select>
    <select id="limitOrderWithOffset" resultType="com.wzil.simplesharding.entity.OrderInfo">
        select * from order_info
        order by num desc
        limit 2,10
    </select>
</mapper>

测试类

@Slf4j
@SpringBootTest
class SimpleShardingApplicationTests {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Test
    void add() {
        for (int i = 0; i < 100; i++) {
            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setName("wzil"+i);
            orderInfo.setCreateTime(new Date());
            orderInfo.setNum(i);
            orderInfoMapper.save(orderInfo);
        }
    }

    @Test
    void delete() {
        Long id=1022869460031111169L;
        orderInfoMapper.deleteById(id);
    }

    @Test
    void update() {
        Long id=1022869460031111169L;
        String name="hello";
        orderInfoMapper.updateNameById(id,name);
    }

    @Test
    void list() {
        List<OrderInfo> list = orderInfoMapper.list();
        System.out.println(list);
    }

    @Test
    void getById() {
        Long id=1022869460031111169L;
        OrderInfo info=orderInfoMapper.getById(id);
        System.out.println(info);
    }
}

4.运行结果

在这里插入图片描述
  此实例运行的是更新的语句,可以看到是对sharding1数据库中的order_info_0进行更新操作的。

自定义分片规则

定义分片类

package com.wzil.simplesharding.config;

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;
import java.util.Properties;

/**
 * @BelongsProject: simple_sharding
 * @BelongsPackage: com.wzil.simplesharding.config
 * @Author: Wuzilong
 * @Description: 轮询分片算法
 * @CreateTime: 2024-07-24 14:21
 * @Version: 1.0
 */

public class RoundRobinShardingAlgorithm implements StandardShardingAlgorithm<String> {

    int currentIndex=0;
    @Override
    public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {
        // 计算当前的索引位置
        currentIndex = (currentIndex + 1) % collection.size();
        // 根据当前索引返回数据源名称
        return (String) collection.toArray()[currentIndex];
    }

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<String> rangeShardingValue) {
        return null;
    }

    @Override
    public Properties getProps() {
        return null;
    }

    @Override
    public void init(Properties properties) {

    }
}


  编写一个分片规则的类去实现StandardShardingAlgorithm接口,去重写doSharding方法。doSharding(Collection collection, PreciseShardingValue preciseShardingValue)这个方法是确定值的分片规则。 doSharding(Collection collection, RangeShardingValue rangeShardingValue)这个方法是范围值的分片规则。根据业务的需求来重写不同的方法。

编写pom文件

        #分片算法
        sharding-algorithms:
          alg_round-robin:
            #指定了算法的类型
            type: CLASS_BASED
            props:
              #标准的分片策略
              strategy: standard
              #算法类的全限定名
              algorithmClassName: com.walker.simplesharding.config.RoundRobinShardingAlgorithm

  编写完之后就可以在上面配置的分库或者分表的规则去指定我们自己定义的alg_round-robin这个类型了。
在这里插入图片描述

总结提升

  分库分表是一种有效的数据库设计策略,能够应对高并发和大数据量的挑战。尽管其带来了复杂性和维护成本,但在许多实际应用中,以提升性能和可扩展性为目标的分库分表依然是一个广泛采用的解决方案。在实施之前,需要深入分析业务需求和技术架构,合理设计分库分表策略,以便最大化其效益。

🎯 此文章对你有用的话记得留言+点赞+收藏哦🎯

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

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

相关文章

SpringBoot上传超大文件导致Cannot read more than 2,147,483,647 into a byte array,问题解决办法

问题描述 报错: java.lang.IllegalArgumentException: Cannot read more than 2,147,483,647 into a byte array at org.apache.commons.io.IOUtils.lambda$toByteArray$0(IOUtils.java:2403) ~[commons-io-2.11.0.jar:2.11.0] at org.apache.commons.io.output.Thre…

python每日学习12:pandas库的用法(1)

python每日学习12&#xff1a;pandas库的用法&#xff08;1&#xff09; 安装 pip install pandas设定系统环境 import pandas as pd #设定自由列表输出最多为 10 行 pd.options.display.max_rows 10 # 显示当前 Pandas 版本号 pd.__version__进入jupyter notebook 页面 在终端…

氧气传感器在汽车制氧检测中的应用

在当今汽车工业中&#xff0c;技术的快速发展不仅带来了驾驶安全性和舒适性的显著提升&#xff0c;还为车辆增加了各种智能功能&#xff0c;以应对不同的驾驶环境和需求。氧气传感器作为一种关键的技术装置&#xff0c;在汽车制氧检测系统中的应用&#xff0c;尤其是针对疲劳驾…

困于数字化泥潭的软件公司|专题报告集

数字化专题报告集链接&#xff1a;https://tecdat.cn/?p36964 在探讨企业数字化转型的进程中&#xff0c;软件公司无疑扮演着举足轻重的角色。它们不仅是技术创新的驱动力&#xff0c;更是连接管理与技术的桥梁。然而&#xff0c;正如许多观察家所指出的那样&#xff0c;软件…

每天五分钟计算机视觉:目标检测模型从RCNN到Fast R-CNN的进化

本文重点 前面的课程中,我们学习了RCNN算法,但是RCNN算法有些慢,然后又有了基于RCNN的Fast-RCNN,Fast R-CNN是一种深度学习模型,主要用于目标检测任务,尤其在图像中物体的识别和定位方面表现出色。它是R-CNN系列算法的一个重要改进版本,旨在解决R-CNN中计算量大、速度慢…

jackson序列化(jackson codec)

Jackson 是一个用于 Java 平台的开源 JSON 库&#xff0c;它提供了灵活且高效的方式来处理 JSON 数据的序列化(Java对象 → JSON字符串)和反序列化(JSON 字符串→ Java对象)。 以下是 Jackson 的一些主要特点和功能&#xff1a; 高性能&#xff1a;Jackson 通过使用基于流的处理…

Ubuntu安装QQ教程

Ubuntu安装QQ教程 腾讯更新Linux版的QQ&#xff0c;这里安装一下&#xff1b; 首先&#xff0c;进入官网找到合适对应的安装包&#xff1b; QQLinux版本官网&#xff1a;https://im.qq.com/linuxqq/index.shtml 我们是ubuntu系统选择X86下的deb版本&#xff0c;如果是arm开…

TikTok养号的网络环境及相关代理IP知识

TikTok作为一个流行的短视频分享平台&#xff0c;其用户量非常庞大&#xff0c;很多商家和个人都会使用TikTok来进行引流和推广。由于TikTok的规则和政策限制了每个用户每天发布视频的数量&#xff0c;因此许多用户会使用多个账号来发布更多的视频以提高曝光率。 然而&#xff…

Android Studio Build窗口出现中文乱码问题

刚安装成功的android studio软件打开工程&#xff0c;编译时下方build窗口中中文是乱码。 解决&#xff1a; 可点击studio状态栏的Help—>Edit Custom VM Options &#xff0c;在打开的studio64.exe.vmoptions文件后面添加&#xff1a;(要注意不能有空格&#xff0c;否则st…

FL Studio Producer Edition 21.2.3.4004中文直版及FL Studio 204如何激活详细教程

在数字化音乐制作的浪潮中&#xff0c;FL Studio 24.1.1.4234的发布无疑又掀起了一股新的热潮。这款由Image-Line公司开发的数字音频工作站&#xff08;DAW&#xff09;软件&#xff0c;以其强大的功能和易用的界面&#xff0c;赢得了全球无数音乐制作人的青睐。本文将深入探讨…

python 图片转文字、语音转文字、文字转语音保存音频并朗读

一、python图片转文字 1、引言 pytesseract是基于Python的OCR工具&#xff0c; 底层使用的是Google的Tesseract-OCR 引擎&#xff0c;支持识别图片中的文字&#xff0c;支持jpeg, png, gif, bmp, tiff等图片格式 2、环境配置 python3.6PIL库安装Google Tesseract OCR 3、安…

使用axios请求后端的上传图片接口

安装axios npm install axios 创建input文件上传标签 <input type"file" name"" id"" change"handleChange" /> 使用axios请求后端的图片上传接口 function handleChange(val) {// new FormData() js内置构造函数&#xff0c…

C++入门基础:C++中的常用操作符练习

开头介绍下C语言先&#xff0c;C是一种广泛使用的计算机程序设计语言&#xff0c;起源于20世纪80年代&#xff0c;由比雅尼斯特劳斯特鲁普在贝尔实验室开发。它是C语言的扩展&#xff0c;增加了面向对象编程的特性。C的应用场景广泛&#xff0c;包括系统软件、游戏开发、嵌入式…

【Nginx】Mac电脑安装nginx

使用brew安装nginx brew install nginx查看nginx信息 brew info nginx启动nginx brew services start nginx验证是否启动成功 浏览器输入地址&#xff1a;127.0.0.1:8080 停止服务 brew services stop nginx进入nginx文件目录 cd /opt/homebrew/etc/nginx重启服务 bre…

轻量化YOLOv7系列:结合G-GhostNet | 适配GPU,华为诺亚提出G-Ghost方案升级GhostNet

轻量化YOLOv7系列&#xff1a;结合G-GhostNet | 适配GPU&#xff0c;华为诺亚提出G-Ghost方案升级GhostNet 需要修改的代码models/GGhostRegNet.py代码 创建yaml文件测试是否创建成功 本文提供了改进 YOLOv7注意力系列包含不同的注意力机制以及多种加入方式&#xff0c;在本文…

分布式光伏并网AM5SE-IS防孤岛保护装置介绍——安科瑞 叶西平

产品简介 功能&#xff1a; AM5SE-IS防孤岛保护装置主要适用于35kV、10kV及低压380V光伏发电、燃气发电等新能源并网供电系统。当发生孤岛现象时&#xff0c;可以快速切除并网点&#xff0c;使本站与电网侧快速脱离&#xff0c;保证整个电站和相关维护人员的生命安全。 应用…

【简历】吉林某一本大学:JAVA秋招简历指导,简历通过率比较低

注&#xff1a;为保证用户信息安全&#xff0c;姓名和学校等信息已经进行同层次变更&#xff0c;内容部分细节也进行了部分隐藏 简历说明 这是一份吉林某一本大学25届计算机专业同学的Java简历。因为学校是一本&#xff0c;所以求职目标以中厂为主。因为学校背景在中厂是正常…

基于Jeecgboot3.6.3的vue3版本前后端分离的流程管理平台

声明一下&#xff1a;因为这个项目license问题无法开源&#xff0c;更多技术支持与服务联系本人或加入我的知识星球提供一些技术服务。 初步完成了基于jeecgboot3.6.3的vue3版本的前后端流程管理平台&#xff0c;基于flowable6.8.1&#xff0c;同时支持bpmn流程设计器与仿钉钉流…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十一章 添加设备树节点

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

利用Django和Ansible实现自动化部署

在软件开发的快节奏世界中&#xff0c;自动化部署是提高开发效率和确保软件质量的关键。Django是一个功能强大的Python Web框架&#xff0c;它允许开发者快速构建安全、可扩展的Web应用。Ansible则是一个简单且强大的自动化工具&#xff0c;它可以用于配置系统、部署软件以及执…