首页 > 其他分享 >ShardingSphereJDBC+MybatisPlus实现分库分表

ShardingSphereJDBC+MybatisPlus实现分库分表

时间:2023-04-05 20:02:19浏览次数:53  
标签:分库 MybatisPlus utf8mb4 ShardingSphereJDBC id user mysql org order

前言

这篇是ShardingSphere-JDBC+Springboot+MybatisPlus+Druid分库分表的简单例子,我们用一个订单表为例,通过简单配置实现数据分片到多个数据库的多个表中。

主要配置和代码已经在文中给出,完整例子可以参考 GitHub - fruitbasket-litchi-shardingjdbc

准备数据库

在一个或两个MySQL服务上创建两个数据库(order_database),执行下面的脚本创建三个订单表(t_order、t_order_0、t_order_1)。

  • t_order只是为了MybatisPlus逆向生成CRUD代码(Mapper、Service和Controller),生成完代码可以删掉
  • t_order_0和t_order_1是保存订单数据的两个分表
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
  `order_id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `description` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

DROP TABLE IF EXISTS `t_order_0`;
CREATE TABLE `t_order_0` (
  `order_id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `description` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=671005327373635585 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

DROP TABLE IF EXISTS `t_order_1`;
CREATE TABLE `t_order_1` (
  `order_id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` int NOT NULL,
  `description` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=671005326614466562 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

引入Maven依赖

<properties>
  <java.version>1.8</java.version>
  <maven.compiler.source>${java.version}</maven.compiler.source>
  <maven.compiler.target>${java.version}</maven.compiler.target>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <spring-boot-dependencies.version>2.3.12.RELEASE</spring-boot-dependencies.version>
  <shardingsphere.version>5.0.0</shardingsphere.version>
  <mybatis-plus-boot-starter.version>3.4.3.4</mybatis-plus-boot-starter.version>
  <lombok.version>1.18.22</lombok.version>
  <mybatis-spring-boot-starter>2.2.0</mybatis-spring-boot-starter>
  <druid.version>1.2.8</druid.version>
  <mybatis-plus-generator.version>3.4.1</mybatis-plus-generator.version>
  <freemarker.version>2.3.31</freemarker.version>
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring-boot-dependencies.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

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

  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus-boot-starter.version}</version>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
  </dependency>

  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>

  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>${mybatis-plus-generator.version}</version>
  </dependency>

  <dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>${freemarker.version}</version>
  </dependency>
</dependencies>

Springboot配置文件

配置数据源,指定两个库(db0、db1)的数据源(druid)、地址和用户名密码等信息。

配置数据库和表的分片算法(sharding-algorithms),并指定分片算法表达式(algorithm-expression),给算法自定义别名(database-inline、t-order-inline)。表达式中(如:db$->{user_id % 2})的意思是数据库名字为db加上$->{user_id % 2}的结果,也就是user_id%2的结果(0或1),拼起来意思是根据user_id分散到数据库db0或db1中。表达式中$->{}也可以写成${},为了避免和SpringBoot配置冲突建议不写${}形式。

这里另外配置了主键生成器(key-generators),并为这个配置自定义别名(snowflake),生成类型为雪花算法(SNOWFLAKE)。

下面tables中的是对一个或多个表进行单独配置。

配置数据库策略(databaseStrategy),指定分片字段(shardingColumn)为user_id、分片算法名称(shardingAlgorithmName)为database-inline(上面自定义的别名)。

再往下配置表策略(tableStrategy)和主键生成策略(keyGenerateStrategy)也是一个意思,用上面定义的配置。

spring:
  shardingsphere:
    # 数据源
    datasource:
      names: db0,db1
      db0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://mysql_node0:3306/order_database?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: root
      db1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://mysql_node1:3306/order_database?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: root

    rules:
      sharding:
        # 分片算法
        sharding-algorithms:
          # 数据库
          database-inline:
            type: INLINE
            props:
              algorithm-expression: db$->{user_id % 2}
          # t-order表
          t-order-inline:
            type: INLINE
            props:
              algorithm-expression: t_order_$->{order_id % 2}

        # 主键生成策略
        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 001

        tables:
          t_order:
            actualDataNodes: db$->{0..1}.t_order_$->{0..1}
            # 数据策略
            databaseStrategy:
              standard:
                shardingColumn: user_id
                shardingAlgorithmName: database-inline
            # 表策略
            tableStrategy:
              standard:
                shardingColumn: order_id
                shardingAlgorithmName: t-order-inline
            # 主键策略
            keyGenerateStrategy:
              column: order_id
              keyGeneratorName: snowflake
    props:
      sql-show: true

mybatis-plus:
  mapper-locations: classpath*:mapper/*.xml

配置结果是添加的数据根据user_id%2确定分片的数据库(db0、db1)/(mysql_node0、mysql_node1),再根据order_id%2保存到分片的表中。也就意味着共有4个表来存储订单数据。

测试接口

这里提供了添加数据(add,http://localhost:8080/order/add)和列出数据(list,http://localhost:8080/order/list)两个接口。

package cn.fruitbasket.litchi.shrdingjdbc.controller;

import cn.fruitbasket.litchi.shrdingjdbc.entity.TOrder;
import cn.fruitbasket.litchi.shrdingjdbc.service.ITOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ThreadLocalRandom;

import static java.util.stream.Collectors.toList;

@RestController
@RequestMapping("order")
public class TOrderController {

    @Autowired
    private ITOrderService itOrderService;

    @GetMapping("add")
    public String add() {
        TOrder order = new TOrder()
                .setUserId(ThreadLocalRandom.current().nextInt(0, Integer.MAX_VALUE))
                .setDescription("测试订单");
        itOrderService.save(order);
        return order.toString();
    }

    @GetMapping("list")
    public String list() {
        return itOrderService.list().stream()
                .map(tOrder -> tOrder.toString() + "<br>").collect(toList()).toString();
    }
}

测试

通过浏览器GET方式访问接口,查看数据库可以看到数据分散到了不同表中。

image-20211126153023201

image-20211126153118175

参考

ShardingSphere - 使用 SPRING BOOT STARTER

GitHub - fruitbasket-litchi-shardingjdbc

标签:分库,MybatisPlus,utf8mb4,ShardingSphereJDBC,id,user,mysql,org,order
From: https://www.cnblogs.com/shuiyao3/p/17290721.html

相关文章

  • MyBatisPlus——条件查询——null值处理与查询投影
    DQL编程控制条件查询——设置查询条件格式一:常规格式 //方式一:按条件查询 QueryWrapperqw=newQueryWrapper(); //10岁到30岁之间的用户 qw.gt("age",10); qw.lt("age",30); List<User>users=userDao.selectList(qw); System.out.println(users);格式......
  • 亿万级分库分表后如何进行跨表分页查询
    亿万级分库分表后如何进行跨表分页查询 目录全局表查询禁止跳页查询按日期的二次查询法大数据集成法NewSql法有序的二次查询法测试分页结果并行查询和排序 前言在常规的应用系统开发中,很少会涉及到需要对数据进行分库或者分表的操作,多数情况下,我们习惯使用OR......
  • 1、分库分表基础理论(一)
    在高性能系统的要求下,复杂的系统当单表数据量增加到几千万甚至上亿条记录时,查询延迟无疑是影响高性能系统的瓶颈。业内提供的解决的方案是分库分表,冷热数据分离。一、分库分表:1、垂直分片:按照业务维度将表拆分到不同的数据库,专库专用,分担数据库压力 2、水平分片:(1)、水平分库......
  • MyBatisPlus---delete删除操作的三种方法
    一、根据id删除1234567891011@Testpublic void deleteById(){    int rows=userMapper.deleteById(1351456313578713090L);    System.out.println("删除条数:" +rows);} @Testpublic void deleteByBatchIds(){    int row......
  • 使用 MybatisPlusCore 自带的雪花算法生成不重复数字
    这里不介绍雪花算法的实现原理,可以自行搜索查阅网上的资料。这里主要介绍雪花算法的使用场景,如何调用第三方类库MybatisPlusCore自带的方法来使用雪花算法。雪花算法的主要使用场景,就是生成不重复的数字,作为数据库表的主键使用。你可能会使用uuid作为主键,但是其占用16个......
  • mycat分库分表一主一从(主从复制)
    一、mysql主从复制1、准备挂载文件为了将配置文件在宿主机做挂载,先运行测试镜像拷贝配置文件1)、拉取镜像dockerpullmysql:8.0.262)、创建测试容器mysql-demodockerrun-it-p3300:3306\--namemysql-demo\-eMYSQL_ROOT_PASSWORD=123456\-dmysql:8.0.26运行......
  • 一款针对EF Core轻量级分表分库、读写分离的开源项目
    在项目开发中,如果数据量比较大,比如日志记录,我们往往会采用分表分库的方案;为了提升性能,把数据库查询与更新操作分开,这时候就要采用读写分离的方案。分表分库通常包含垂直分......
  • 亿万级分库分表后如何进行跨表分页查询
    前言在常规的应用系统开发中,很少会涉及到需要对数据进行分库或者分表的操作,多数情况下,我们习惯使用ORM带来的便利,且使用连接查询是一种高效率的开发方式,就算涉及到分表的......
  • MyBatisPlus快速上手
    ORM介绍ORM(ObjectRelationalMapping,对象关系映射)是为了解决面向对象与关系数据库存在的互不匹配现象的一种技术。ORM通过使用描述对象和数据库之间映射的元数据将程......
  • 关于数据库分库分表的一点想法
    作者:京东物流 何小坡1开篇面对数据的激增,相信大家也都有分库分表的一些方案,这次的这个分享,算是自己的一个想法,可以当做一个参考方案,也欢迎相互讨论。话不多说,直接进入主......