水平分表、分库和垂直分表、分库和公共表的代码实现和讲解

news2024/12/23 5:30:48

文章目录

  • 一、环境准备
  • 二、水平分表
    • 1.概念
    • 2.代码
  • 三、水平分库
    • 1.概念
    • 2.代码
  • 四、垂直分表
    • 1.概念
    • 2.代码
  • 五、垂直分库
    • 1.概念
    • 2.代码
  • 六、公共表
    • 1.概念
    • 2.代码

一、环境准备

  • 操作系统:Win10
  • 数据库:MySQL5.7
  • JDK:64位 jdk1.8.0_202
  • 应用框架:spring-boot-2.1.3.RELEASE
  • Sharding-JDBC:sharding-jdbc-spring-boot-starter-4.0.0-RC1

对应的pom.xml依赖代码

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>


  <groupId>com.yjq.programmer</groupId>
  <artifactId>ShardingJDBC</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>ShardingJDBC</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- 引入mysql连接依赖 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 引入sharding-jdbc连接依赖 -->
    <dependency>
      <groupId>org.apache.shardingsphere</groupId>
      <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
      <version>4.0.0-RC1</version>
    </dependency>
    <!--引入阿里巴巴druid连接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.19</version>
    </dependency>
    <!-- 引入测试依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- 集成mybatis -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.3.2</version>
    </dependency>
    <!-- 集成junit测试 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>

        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

      </plugins>
    </pluginManagement>
  </build>
</project>

二、水平分表

1.概念

水平分表是在同一个数据库内,把同一个表的数据按一定规则拆分到多个中。
因此,目前我在一个数据库中准备了两个表,t_user_1t_user_2,如下图。
在这里插入图片描述
表结构:

CREATE TABLE `t_user_1` (
  `id` bigint(20) NOT NULL,
  `name` varchar(100) DEFAULT NULL,
  `sex` int(2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.代码

①我们先来看下我们的SpringBoot的配置文件代码。

server.port=8081
#1800s
server.servlet.session.timeout=1800
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

#定义数据源
spring.shardingsphere.datasource.names=m1

spring.shardingsphere.datasource.m1.url=jdbc:mysql://127.0.0.1:3306/db_user1?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf8
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=
spring.shardingsphere.datasource.m1.driver‐class‐name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource

# 指定t_user表的数据分布情况,配置数据节点
spring.shardingsphere.sharding.tables.t_user.actual‐data‐nodes=m1.t_user_$->{1..2}

# 指定t_user表的主键生成策略为SNOWFLAKE
spring.shardingsphere.sharding.tables.t_user.key‐generator.column=id
spring.shardingsphere.sharding.tables.t_user.key‐generator.type=SNOWFLAKE

# 指定t_user表的分表策略,分表策略包括分片键和分片算法
spring.shardingsphere.sharding.tables.t_user.table‐strategy.inline.sharding‐column=id
spring.shardingsphere.sharding.tables.t_user.table‐strategy.inline.algorithm‐expression=t_user_$->{id % 2 + 1}


# 控制台日志配置
logging.level.root=info
logging.level.com.yjq.programmer.dao=debug

# 打开sql输出日志
spring.shardingsphere.props.sql.show=true

#mapper文件扫描路径
mybatis.mapper-locations=classpath*:mappers/**/*.xml

配置文件代码说明

  • 首先定义数据源m1,并对m1进行实际的参数配置。
  • 指定t_user表的数据分布情况,他分布在m1.t_user_1,m1.t_user_2。
  • 指定t_user表的主键生成策略为SNOWFLAKE,SNOWFLAKE是一种分布式自增算法,保证id全局唯一。
  • 定义t_user分表策略,id为偶数的数据落在t_user_1,为奇数的落在t_user_2,所以分表策略的表达式为t_user_$->{id% 2 + 1}。

踩坑注意! 如果启动项目有如下报错,可能是配置文件中的->没有用英文类型的。
在这里插入图片描述
在这里插入图片描述

②然后接下来就写我们的dao层、mapper层和单元测试的代码,去测试我们的水平分表情况下插入查询的结果。

dao

public interface UserDao {

    int insertUser(User user);

    List<User> selectUser();
}

mapper

<?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">
<mapper namespace="com.yjq.programmer.dao.UserDao">

    <insert id="insertUser" parameterType="com.yjq.programmer.entity.User">
        insert into t_user(name) values (#{name})
    </insert>


    <select id="selectUser" resultType="com.yjq.programmer.entity.User">
        select * from t_user
    </select>
</mapper>

单元测试

@Test
public void testShardingJDBCInsert() {
    User user = new User();
    for(int i=0; i<10; i++) {
        user.setName("小明" + i);
        if(userDao.insertUser(user) == 1) {
            logger.info("插入成功!");
        } else {
            logger.info("插入失败!");
        }
    }
}


@Test
public void testShardingJDBCSelect() {
    List<User> userList = userDao.selectUser();
    logger.info("查询结果:{}", JSONObject.toJSONString(userList));
}

③结果说明
插入
id为奇数的被插入到t_user_1表,为偶数的被插入到t_user_2表,达到预期目标。
查询
sharding-jdbc分别去不同的表检索数据,达到预期目标;如果有传入id进行查询,sharding-jdbc也会根据t_user的分表策略去不同的表检索数据

三、水平分库

1.概念

水平分库是把同一个表的数据按一定规则拆分到不同的数据库中,每个库可以放在不同的服务器上。
现在,我在水平分表的基础上多加了一个db_user2的数据库。
在这里插入图片描述
然后两个数据库中的表结构是一致的,表结构和上面水平分表用的保持一样。
在这里插入图片描述

2.代码

①我们先来看下我们的SpringBoot的配置文件代码。

server.port=8081
#1800s
server.servlet.session.timeout=1800
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

#定义数据源
spring.shardingsphere.datasource.names=m1,m2

spring.shardingsphere.datasource.m1.url=jdbc:mysql://127.0.0.1:3306/db_user1?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf8
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=
spring.shardingsphere.datasource.m1.driver‐class‐name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource

spring.shardingsphere.datasource.m2.url=jdbc:mysql://127.0.0.1:3306/db_user2?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf8
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=
spring.shardingsphere.datasource.m2.driver‐class‐name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource

# 分库策略
spring.shardingsphere.sharding.tables.t_user.database‐strategy.inline.sharding‐column=sex
spring.shardingsphere.sharding.tables.t_user.database‐strategy.inline.algorithm‐expression=m$->{sex % 2 + 1}

# 指定t_user表的数据分布情况,配置数据节点
spring.shardingsphere.sharding.tables.t_user.actual‐data‐nodes=m$->{1..2}.t_user_$->{1..2}

# 指定t_user表的主键生成策略为SNOWFLAKE
spring.shardingsphere.sharding.tables.t_user.key‐generator.column=id
spring.shardingsphere.sharding.tables.t_user.key‐generator.type=SNOWFLAKE

# 指定t_user表的分表策略,分表策略包括分片键和分片算法
spring.shardingsphere.sharding.tables.t_user.table‐strategy.inline.sharding‐column=id
spring.shardingsphere.sharding.tables.t_user.table‐strategy.inline.algorithm‐expression=t_user_$->{id % 2 + 1}


# 控制台日志配置
logging.level.root=info
logging.level.com.yjq.programmer.dao=debug

# 打开sql输出日志
spring.shardingsphere.props.sql.show=true

#mapper文件扫描路径
mybatis.mapper-locations=classpath*:mappers/**/*.xml

配置文件代码说明

  • 配置了两个数据源,分配指向两个不同的数据库db_user1和db_user2。
  • 配置分库策略,sex字段为偶数的数据落在m1数据源,为奇数的落在m2数据源,所以分库策略的表达式为m$->{sex % 2 + 1}。
  • 配置分表策略,分表策略和上面水平分表保持一致。
  • 也就是当有数据来时,先根据sex字段判断落入哪个数据源,然后再根据id字段来判断落入哪个表中。

②然后接下来就写我们的dao层、mapper层和单元测试的代码,去测试我们的水平分表情况下插入查询的结果。

dao

public interface UserDao {

    int insertUser(User user);

    List<User> selectUser(User user);
}

mapper

<?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">
<mapper namespace="com.yjq.programmer.dao.UserDao">

    <insert id="insertUser" parameterType="com.yjq.programmer.entity.User">
        insert into t_user(name, sex) values (#{name}, #{sex})
    </insert>


    <select id="selectUser" parameterType="com.yjq.programmer.entity.User" resultType="com.yjq.programmer.entity.User">
        select * from t_user t where t.sex = #{sex} and t.id = #{id}
    </select>
</mapper>

单元测试

@Test
public void testShardingJDBCInsert() {
    User user = new User();
    for(int i=0; i<10; i++) {
        user.setName("小明" + i);
        user.setSex(1);
        if(userDao.insertUser(user) == 1) {
            logger.info("插入成功!");
        } else {
            logger.info("插入失败!");
        }
    }
}


@Test
public void testShardingJDBCSelect() {
    User user = new User();
    user.setSex(1);
    user.setId(821357967667363840L);
    List<User> userList = userDao.selectUser(user);
    logger.info("查询结果:{}", JSONObject.toJSONString(userList));
}

③结果说明
插入
sex字段为奇数的数据落入m2数据源,为偶数的落入m1数据源。同时id字段值为奇数的,插入t_user_2表中,为偶数的插入t_user_1表中,达到预期目标。
查询
sharding-jdbc分别去不同的表检索数据,达到预期目标;如果有传入sex进行查询,sharding-jdbc会根据t_user的分库策略去锁定查哪个库,如果有传入id进行查询,sharding-jdbc会根据t_user的分表策略去锁定查哪个表

四、垂直分表

1.概念

垂直分表一般就是把表的结构进行改造,关于如何改造,可以浏览我的另一篇博客:
分库分表:垂直分库、垂直分表、水平分库、水平分表四个概念
大致的思路就是:将一个表按照字段分成多表,每个表存储其中一部分字段。

2.代码

无代码,垂直分表属于表结构设计层面。

五、垂直分库

1.概念

垂直分库就是在垂直分表把表进行分类后,放到不同的数据库中。每个库可以放在不同的服务器上,它的核心理念是专库专用。关于如何改造,同样可以浏览我的另一篇博客:
分库分表:垂直分库、垂直分表、水平分库、水平分表四个概念

2.代码

无代码,垂直分库属于数据库设计层面。

六、公共表

1.概念

公共表属于系统中数据量较小,变动少,而且属于高频联合查询的依赖表。参数表、数据字典表等属于此类型。可以将这类表在每个数据库都保存一份,所有更新操作都同时发送到所有分库执行。

2.代码

①只需要在SpringBoot的配置文件中加入下面这行来指明公共表就行。
如果有多个公共表,用逗号拼接就行

#公共表设置
spring.shardingsphere.sharding.broadcast‐tables=t_dict

②然后接下来就写我们的dao层、mapper层和单元测试的代码,去测试我们的公共表的插入的结果。
dao

public interface DictDao {

    int insertDict(Dict dict);
}

mapper

<?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">
<mapper namespace="com.yjq.programmer.dao.DictDao">

    <insert id="insertDict" parameterType="com.yjq.programmer.entity.Dict">
        insert into t_dict(id, name) values (#{id}, #{name})
    </insert>


</mapper>

单元测试

@Test
public void testShardingJDBCInsertDict() {
    Dict dict = new Dict();
    dict.setId(1);
    dict.setName("字典名称");
    if(dictDao.insertDict(dict) == 1) {
        logger.info("插入成功!");
    } else {
        logger.info("插入失败!");
    }
}

③结果说明
插入
插入的数据在每个库中的对应的公共表中都能看到,达到预期目标。

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

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

相关文章

DOS和DDOS攻击和防御(ATTACK)

目录 一、DOS攻击和DDOS攻击的区别 第一、我们可以从他们两个的英文全称上来看初步的区别 第二、攻击方法不同 二、DOS和DDOS攻击的实现方式 1.DOS攻击 1、SYN Flood(是DOS和DDOS攻击方式之一) 2、UDP洪水攻击 3、Ping洪流攻击 4、teardrop攻击 5、Land攻击 6、Smurf攻击 7、Fr…

【 uniapp - 黑马优购 | 登录与支付 1】登录组件布局实现、用户信息布局与渲染

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;讨厌编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;小新爱学习. &#x1f43c;个人WeChat&#xff1a;见文末 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;…

设计模式-原型模式

设计模式-原型模式一 官方定义二 案例演示解决方案一 - 一般实现方式实现过程案例分析解决方案二使用场景实现过程一实现过程 二案例分析三 浅拷贝和深拷贝浅拷贝问题演示实现过程案例分析解决方案-----深拷贝实现方式一&#xff1a;重写clone()方法扩展思考一 官方定义 原型模…

在VMware 虚拟机(Win7)中还原真机Ghost备份的Win10系统

要求&#xff1a; 将真机Ghost备份的Win10系统还原到VMware安装的虚拟机&#xff08;Win7&#xff09;上 真机&#xff08;物理机&#xff09;&#xff1a;win10pro_pure_20220709.GHO &#xff08;备份的GHO文件&#xff09;&#xff1b;安装模式&#xff1a;Win10UEFIGPT 虚…

HashMap源码学习:红黑树原理详解

前言 JDK1.8后的HashMap引入了红黑树&#xff0c;在学习HashMap源码之前&#xff0c;了解了红黑树原理&#xff0c;及其如何通过代码进行实现后&#xff0c;在整体的看HashMap的源码就会简单很多。 概述 红黑树的特性 根节点必须是黑色节点。节点是红色或黑色。所有叶子都是…

Redis原理

Redis内部使用的是文件事件处理器file event handler,它是单线程的,所以Redis叫做单线程模型。它采用IO多路复用机制同时监听多个socket,将产生事件的socket压入内存队列中,事件分派器根据socket上的事件类型来选择对应的事件处理器进行处理。文件事件处理器包含4个部分:多…

【Java寒假打卡】Java基础-线程池

【Java寒假打卡】Java基础-线程池概述基本使用Executors创建指定上限的线程对象线程池-ThreadPoolExecutorvolatile概述 基本使用 package com.hfut.edu.test12;import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class test1 {publ…

java+springboot笔记2023003

java的版本发布&#xff1a; 编译型语言是指使用专门的编译器&#xff0c;针对特定平台&#xff08;操作系统&#xff09; 将某种高级语言源代码一次性“翻译”成可被该平台硬件执行的机器码&#xff08;包括机器指令和操作数&#xff09;&#xff0c;并包装成该平台所能识别的…

Linux下更新curl版本

一、前景 由于低版本的curl存在一定的漏洞&#xff0c;会对我们的服务器安全造成问题&#xff0c;所以&#xff0c;我们需要将curl由低版本安装到高版本。 二、步骤 1、首先检测服务器安装的curl版本 curl --version 2、查看服务器安装的curl的安装包 rpm -qa curl 3、卸载…

基于springboot+mybatis+mysql+jsp房屋租赁管理系统(含论文)

基于springbootmybatismysqljsp房屋租赁管理系统&#xff08;含论文&#xff09;一、系统介绍二、所用技术三、功能展示三、其它系统四、获取源码一、系统介绍 包括管理员、房东、租客三种角色&#xff0c;外加游客(未登录情况) 出租类型包含整租和合租 权限 游客 < 租客 …

适合编程初学者的开源项目:小游戏2048(鸿蒙ArkTS版)

目标 为编程初学者打造入门学习项目&#xff0c;使用各种主流编程语言来实现。 2048游戏规则 一共16个单元格&#xff0c;初始时由2或者4构成。 1、手指向一个方向滑动&#xff0c;所有格子会向那个方向运动。 2、相同数字的两个格子&#xff0c;相遇时数字会相加。 3、每次…

用 JavaScript 写一个新年倒计时

目录前言&#xff1a;主题&#xff1a;运行结果&#xff1a;对应素材&#xff1a;代码实现思路&#xff1a;运行代码&#xff1a;春节的由来&#xff1a;总结&#xff1a;前言&#xff1a; 在春节即将到来&#xff0c;钟声即将响起&#xff0c;焰火即将燃起的日子里&#xff0c…

Kubernetes_CRD自定义资源

系列文章目录 文章目录系列文章目录前言一、CRD操作命令1.1 定义一种资源并查看1.2 使用刚刚定义的资源二、CRD效果演示2.1 实践&#xff1a;定义一种资源并查看2.2 实践&#xff1a;使用刚刚定义的资源总结前言 CRD就是自定义资源&#xff0c;就是自定义 apiVersionKind 参考…

TreeMap 原理实现及常用方法

TreeMap概述 红黑树回顾 TreeMap构造 put方法 get 方法 remove方法 遍历 总结 一. TreeMap概述 TreeMap存储K-V键值对&#xff0c;通过红黑树&#xff08;R-B tree&#xff09;实现&#xff1b; TreeMap继承了NavigableMap接口&#xff0c;NavigableMap接口继承了Sort…

蓝桥杯STM32G431RBT6学习——LED

蓝桥杯STM32G431RBT6学习——LED 前言 LED为每年必考考点&#xff0c;也是入门的基础&#xff0c;国信长天的开发板LED硬件如下&#xff1a; 经典的锁存器控制&#xff0c;因为LED所用引脚与LCD重叠&#xff0c;因此通过锁存器进行控制其状态。当74HC573的LE引脚&#xff08…

C语言综合练习5:快译通下

1 词典文件介绍 前面建立的词典&#xff0c;只有两个单词&#xff0c;现在我们要建立一个上万个单词的词典&#xff0c;所有单词及其翻译都在一个名为dict.txt的文件&#xff08;词典文件&#xff09;中 每个单词有两行&#xff0c;其中一行是单词原文&#xff0c;下一行是对…

Redis中的事务和乐观锁实现

redis事务相关命令&#xff1a; 开启事务&#xff1a;multi 关闭事务&#xff1a;discard 提交事务&#xff1a;exec 正常执行事务情况&#xff1a; 127.0.0.1:6379> multi OK 127.0.0.1:6379> set name zhangsan QUEUED 127.0.0.1:6379> set age 20 QUEUED 127.0.0.1…

AJAX这一篇就够啦~

AJAX这一篇就够啦~AJAX1、AJAX概述1.1 AJAX简介1.2 XML简介1.3 AJAX的特点2、HTTP相关2.1 HTTP概述2.2 请求报文2.3 响应报文2.4 常见的响应状态码2.5 不同类型的请求及其作用2.6 一般http请求 与 ajax请求3、原生AJAX的使用3.1 准备工作3.2 核心对象3.3 GET请求3.4 POST请求3.…

新岁序开,和Jina AI共同码梦! (奖品攻略大揭秘)

Jina AI 北京、深圳、柏林、湾区的小伙伴给您拜年啦&#xff01; Jina AI 开源社区致力于促进 多模态 AI 技术 的应用落地以及传播&#xff0c;一直以来&#xff0c;我们都为拥有这样一个全球化、多元化和高速发展的社区而感到自豪和感激&#xff01;正值新年之际&#xff0c;我…

从C和C++内存管理来谈谈JVM的垃圾回收算法设计-下

从C和C内存管理来谈谈JVM的垃圾回收算法设计-下引言基本概念对象GC ROOTS垃圾回收常见算法标记清除优缺点引用计数优缺点部分标记清除算法优缺点复制算法优缺点多空间复制算法标记整理(标记压缩)优缺点分代设计HotSpot具体实现跨代引用并发可行性经典垃圾回收器Serial新生代垃圾…