SpringBoot+ShardinggJDBC(5.2.0)实现分库分表

前言

  • 本文提供了在SpringBoot环境下使用ShardingJDBC,可以参考ShardingJDBC的使用手册
  • 我们其实都在使用垂直分库和垂直分表,垂直分库就是我们微服务中每个微服务都有自己的库,一般就是根据业务来拆分库;垂直分表也就是我们平时通过外键关联起来的表,比如商品表和商品详情表;所以本文介绍的是水平分库和水平分表,水平分库和水平分表都是将一个大的库或者一个大的表按照水平方向分成多个库和多个表,库与库之间的表相同,内容不同;表与表之间字段相同,内容不同。
  • 首先声明一点,ShardingJDBC配置流程是大同小异的,但是不同版本的配置属性是有比较多的差别的,所以不同的版本以下配置可能不适用,另外ShardingJDBC提供的也不是很完整,所以碰到问题时需要大家自己多搜索,多尝试。

本文使用到的环境

【注意】以下的依赖都是必须的,其他依赖可以根据项目的需求加入,

  • SpringBoot依赖
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.16</version>
        <relativePath/>
    </parent>
  • Mysql依赖,以下两个mysql包都可以
		//mysql包下的
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.31</version>
        </dependency>
		//com/mysql包下的
		<dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.31</version>
        </dependency>
  • Druid依赖,注意这个一定要用原生的,不要用SpringBoot整合的
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.18</version>
        </dependency>
  • Mybatis依赖
 			<dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.3.1</version>
            </dependency>
  • ShardingJDBC依赖
		<dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.2.0</version>
        </dependency>

准备数据库

  • 我准备了两个数据库(blog1,blog2,两个数据库内容是完全相同的,进行水平分库
  • 每个库中准备两个表(tb_article_type1,tb_article_type2,两张表的内容是完全相同的,即两个库中这四张表都是完全相同的),进行水平分表。
    【注意】这四张表中初始都没有数据,并且他们的主键不能是自增(因为后面要用雪花算法来生成主键,保证主键在四张表中都唯一,并且通过主键来确定这个数据放哪张表)
    在这里插入图片描述
  • 四张表中的字段,我们根据status来分库
    在这里插入图片描述

配置yml

  • mybatis的配置和以前一样,只是将之前的单个数据源用shardingjdbc配置了多个数据源
spring:
  shardingsphere:
    # 数据源配置
    datasource:
      # 数据源名称,多数据源以逗号分隔
      names: blog1,blog2
      blog1: #上面定义的数据源的名称
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3307/blog1?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
        username: root
        password: 123456
      blog2: #上面定义的数据源的名称
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3307/blog2?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
        username: root
        password: 123456
    # 分库分表规则配置
    rules:
      sharding:
        key-generators: # 主键的生成策略
          snowflake:
            type: SNOWFLAKE # 使用雪花算法生成主键
        # 分库分表算法配置
        sharding-algorithms:
          #分库算法配置
          database-inline:
            # 算法类型
            type: INLINE
            props:
              # 分片算法的行表达式(分为两个库,分别为blog1和blog2,blogs是固定的,后面的表达式是根据status的值决定放在1还是2,$->{你的分库表达式})
              algorithm-expression: blog$->{status % 2 + 1}
          # 分表算法配置
          table-inline:
            # 分片算法类型
            type: INLINE
            props:
              # 分片算法的行表达式,和分库同理
              algorithm-expression: tb_article_type$->{id % 2 + 1}
        tables:
          # 逻辑表名称
          tb_article_type: #分表的表名前缀
            key-generate-strategy:
              column: id  #根据哪一列分表,我是根据id列,所以填id
              key-generator-name: snowflake  #id生成算法
            # 行表达式标识符可以使用 ${...} 或 $->{...},但前者与 Spring 本身的属性文件占位符冲突,因此在 Spring 环境中使用行表达式标识符建议使用 $->{...}
            actual-data-nodes: blog$->{1..2}.tb_article_type$->{1..2}  #最终是在哪个库的哪张表中
            # 分库策略
            database-strategy:
              standard:
                # 分片列名称
                sharding-column: status  #分库是根据哪一列分的,我用的是status,所以填status
                # 分片算法名称
                sharding-algorithm-name: database-inline #database-inline要和上面分库算法配置名称保持一致
            # 分表策略
            table-strategy:
              standard:
                # 分片列名称
                sharding-column: id
                # 分片算法名称
                sharding-algorithm-name: table-inline #table-inline要和上面分表算法配置名称保持一致
    # 属性配置
    props:
      # 展示修改以后的sql语句
      sql-show: true

数据测试

  • 测试接口这些就不展示了,因为每个人的业务不同,但是新增都是大同小异的
  • 我使用的是Apifox自动生成的数据进行测试的,怎么使用Apifox生成接口文档可以参见我的ApiFox接口文档的使用
    在这里插入图片描述
  • 以下是四个数据库所存的数据,我们只需关注status和id,因为我们就是通过这两个字段进行水平分库分表的。
    【blog1.tb_article_type1】可以看到status都是偶数,所以(status % 2 +1)=1,在blog1中,id都是偶数,所以(id % 2 +1)=1 在tb_article_type1中。
    在这里插入图片描述
    【blog1.tb_article_type2】可以看到status都是偶数,所以(status % 2 +1)=1,在blog1中,id都是奇数,所以(id % 2 +1)=2 在tb_article_type2中。
    在这里插入图片描述
    【blog2.tb_article_type1】可以看到status都是奇数,所以(status % 2 +1)=2,在blog2中,id都是偶数,所以(id % 2 +1)=1 在tb_article_type1中。
    在这里插入图片描述
    【blog2.tb_article_type2】可以看到status都是奇数,所以(status % 2 +1)=2,在blog2中,id都是奇数,所以(id % 2 +1)=2 在tb_article_type2中。
    在这里插入图片描述

总结

  • 以上就是水平分库分表的一个小案例,只是对其中一张表进行了水平分表,对多张表进行水平分表步骤类似。