分库分表--shardingjdbc

文章目录

  • 前言
  • 一、shardingjdbc
    • 简介
    • 作用
  • 二、如何使用
    • 1.我有个表现在体量太大了,我想做分库分表
    • 2.开始改造
      • 1 引入shardingjdbc
      • 2 更改yml文件
      • 3 测试看效果
    • 3.旧数据迁移
    • 4.其他分库类型
    • 5 部分配置说明
  • 总结


前言

当项目开始的时候,没有想到后续的分库分表的话,其实对于后续的分库分表操作多少会有一些较难处理的,所以一般分库分表都是在开始的时候就提前已经规划了,已经预留了口子,之后才能顺利的进行;
其实也不是必须要分库分表,由于国产高性能数据库等的出现,例如 tidb,完全遵守sql92标准,其实直接换上这个也是个非常不错的选择;


一、shardingjdbc

简介

  • Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架
  • 市面上常用的 例如 jpa jdbctemplete mybatis mp 原生的 jdbc都是ok的
  • 它对于原有代码的改动很小,无入侵
  • 支持任意实现JDBC规范的数据库,目前支持MySQL,TIDB, Oracle,SQLServer和PostgreSQL
  • 支持分布式事务
  • 支持各种连接池

作用

  • 分库分表: 单库分表,分库后不再分表,分库分表
  • 分布式事务
  • 读写分离
  • 数据库主键生成策略
  • 分库分表路由策略

二、如何使用

1.我有个表现在体量太大了,我想做分库分表

我的库和表
分库分表--shardingjdbc_第1张图片

所以这就是我的springboot项目,引入了mp,然后可以实现单表的增删改查

2.开始改造

1 引入shardingjdbc

    
            org.apache.shardingsphere
            sharding-jdbc-spring-boot-starter
            4.1.1
        

2 更改yml文件

新增两个表:
分库分表--shardingjdbc_第2张图片

# 水平单库分表配置
spring:
  main:
    allow-bean-definition-overriding: true
  sharding-sphere:
    datasource:
      m1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://localhost:3306/coursedb?serverTimezone=GMT%2B8
        username: root
      names: m1
    props:
      sql:
        show: true
    sharding:
      tables:
        course:
          actual-data-nodes: m1.course_$->{1..2}
          key-generator:
            column: cid
            type: SNOWFLAKE
          table-strategy:
            inline:
              algorithm-expression: course_$->{cid%2+1}
              sharding-column: cid

我现在相当于之前的代码没有任何改动
然后yml更改为了shardingjdbc 分库分表配置
我将要应用的表为 coursedb 库中的 course_1 和 course_2

至此,sardingjdbc已经这个完毕了! 就是这么简单,直接看效果

3 测试看效果

  • 新建测试类
@SpringBootTest
@RunWith(SpringRunner.class)
class DemoShardingJdbcApplicationTests {

    @Resource
    CourseMapper courseMapper;

    /**
     * 插入多条,分配到不同的表中
     */
    @Test
    void insert() {
        for (int i = 0; i < 10; i++) {
            Course record = new Course();
            record.setCname("java" + i);
            record.setCstatus("1");
            record.setUserId(RandomUtil.randomLong(50));
            System.out.println(courseMapper.insert(record));
        }
    }
 }
  • 看一段日志
 ShardingSphere-SQL: Logic SQL: INSERT INTO course  ( cid,
cname,
user_id,
cstatus )  VALUES  ( ?,
?,
?,
? )

ShardingSphere-SQL: Actual SQL: m1 ::: INSERT INTO course_2  ( cid,
cname,
user_id,
cstatus )  VALUES  (?, ?, ?, ?) ::: [1646822909442260993, java9, 9, 1]

分库分表--shardingjdbc_第3张图片
分库分表--shardingjdbc_第4张图片
分库分表--shardingjdbc_第5张图片

原始sql Logic SQL: INSERT INTO course
实际执行的sql Actual SQL: m1 ::: INSERT INTO course_2
没错,之前的表名称不用动,但是实际上已经在用 course_1 和 course_2

3.旧数据迁移

  • 由于之前的course表中还有历史数据,所以需要迁移,因为他已经名存实亡了,以后也不再会用它了,那么就有点小复杂了
    • 迁移单张表的数据还好,但是可能涉及到其他数据库
    • 如果主键与分库分表之后的类型不一致,就更麻烦了

4.其他分库类型

  • 水平分库 表不再分配置
# 水平分库 表不再分配置
spring:
  main:
    allow-bean-definition-overriding: true
  sharding-sphere:
    datasource:
      m1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://localhost:3306/coursedb0?serverTimezone=GMT%2B8
        username: root
      m2:
        driver-class-name: com.mysql.cj.jdbc.Driver
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://localhost:3306/coursedb1?serverTimezone=GMT%2B8
        username: root
      names: m1,m2
    props:
      sql:
        show: true
    sharding:
      tables:
        course:
          actual-data-nodes: m$->{1..2}.course
          key-generator:
            column: cid
            type: SNOWFLAKE
          table-strategy:
            inline:
              algorithm-expression: course
              sharding-column: cid

  • 水平分库 分表配置
# 水平分库 分表配置
spring:
  main:
    allow-bean-definition-overriding: true
  sharding-sphere:
    datasource:
      m1:
        driver-class-name: com.mysql.cj.jdbc.Driver
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://localhost:3306/coursedb0?serverTimezone=GMT%2B8
        username: root
      m2:
        driver-class-name: com.mysql.cj.jdbc.Driver
        password: root
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://localhost:3306/coursedb1?serverTimezone=GMT%2B8
        username: root
      names: m1,m2
    props:
      sql:
        show: true
    sharding:
      # 所有不分片的表,默认执行库
      default-data-source-name: m1
      tables:
        course:
          actual-data-nodes: m$->{1..2}.course_$->{1..2}
          key-generator:
            column: cid
            type: SNOWFLAKE
          database-strategy:
            inline:
              algorithm-expression: m$->{user_id % 2 +1}
              # 配置数据库字段 不是实体类中的字段
              sharding-column: user_id
          table-strategy:
            inline:
              algorithm-expression: course_$->{cid % 2 +1}
              sharding-column: cid

5 部分配置说明

      tables:
        course:
          actual-data-nodes: m$->{1..2}.course_$->{1..2}
          key-generator:
            column: cid
            type: SNOWFLAKE
          database-strategy:
            inline:
              algorithm-expression: m$->{user_id % 2 +1}
              # 配置数据库字段 不是实体类中的字段
              sharding-column: user_id
          table-strategy:
            inline:
              algorithm-expression: course_$->{cid % 2 +1}
              sharding-column: cid
  • mKaTeX parse error: Expected group after '_' at position 16: ->{1..2}.course_̲->{1…2} 代表笛卡尔乘积,相当于m1.course_1,m1.course_2,m2.course_1,m2.course_2
  • database-strategy 分库策略: 选择 m1 / m2
  • user_id 分库策略具体算法字段,具体算法 m$->{user_id % 2 +1}
  • table-strategy 分表策略: 选择 course_1 / course_2
  • cid 分表策略具体算法字段,具体算法 course_$->{cid % 2 +1}
当 user_id 为偶数, cid 为偶数, 选择的应该是 m1.course_1
当 user_id 为偶数, cid 为奇数, 选择的应该是 m1.course_2
当 user_id 为奇数, cid 为偶数, 选择的应该是 m2.course_1
当 user_id 为奇数, cid 为奇数, 选择的应该是 m2.course_2

总结

所有代码均在gitee上: 项目地址
后续还有分页,排序,分布式事务等

你可能感兴趣的:(mybatis,java,数据库)