ShardingJdbc-水平分库

ShardingJdbc-水平分库

水平分库

  • 表结构相同、记录不同、所属库不同
  • 多个库中表记录数和才是总的记录数
  • 通常根据主键ID进行分表,这里采用奇偶策略

案例

  • 建立库 sharding_demo-1、sharding_demo-2
  • 每个库建立表 user_1、user_2 表结构相同
  • id 为主键,bigint 类型
  • clientId,bigint 类型
  • 分库规则
    • client_id 为偶数的记录存储到 sharding_demo-1 库
    • client_id 为奇数的记录存储到 sharding_demo-2 库
  • 分表规则
    • id 为偶数的记录存储到 user_1表
    • id 为奇数的记录存储到 user_2表

建表语句

库(sharding_demo-1、sharding_demo-2)自行创建

Bash 复制代码
CREATE TABLE `user_1`  (
  `id` bigint NOT NULL,
  `client_id` bigint NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `age` int NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

项目代码

自行创建 SpringBoot 项目 ShardingJDBCDemo

  • 导入依赖
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 https://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.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.study</groupId>
    <artifactId>ShardingJDBCDemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ShardingJDBCDemo</name>
    <description>ShardingJDBCDemo</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!-- mysql 数据库连接依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 数据库连接池依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.20</version>
        </dependency>
        <!-- MybatisPlus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>
        <!-- shardingsphere 必须的依赖 sharding-jdbc  !!! -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>
        <!-- 简化实体get/set依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  • 创建用户实体类
java 复制代码
package com.study.shardingjdbcdemo.demo.entity;

import lombok.Data;

@Data
public class User {

    private Integer id;
    private String name;
    private Integer age;
    private Integer clientId;
}
  • 编写 mapper
java 复制代码
package com.study.shardingjdbcdemo.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.study.shardingjdbcdemo.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}
  • 启动类增加mapper扫描
java 复制代码
package com.study.shardingjdbcdemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
@MapperScan("com.study.shardingjdbcdemo.demo.mapper")
public class ShardingJdbcDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShardingJdbcDemoApplication.class, args);
    }

}

水平分库分表配置

application.yml 配置详解

yaml 复制代码
# 水平分库分表   多库多表
server:
  port: 8081

spring:
  main:
    # 一个实体类对应两张表,覆盖
    allow-bean-definition-overriding: true
  shardingsphere:
    datasource:
      names: ds1,ds2 # 多数据源
      ds1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3307/sharding_demo-1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
        username: root
        password: r#dcenter9
      ds2:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://127.0.0.1:3307/sharding_demo-2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
        username: root
        password: r#dcenter9
    sharding:
#      default-database-strategy: # 默认分库策略  所有表的分库策略
#        inline:
#          # 分库列
#          sharding-column: id
#          # 分库算法  id 偶数存储到 user_1 奇数存储到 user_2
#          # 除2取余数 要么是0要么是1 然后给+1 对应的就是user_1 user_2
#          algorithm-expression: ds$->{id % 2 + 1}
      tables:
        user:
          # 分表规则 哪个库(ds1)哪张表(user)以及表名称规则(user_1、user_2)
          #  ds1  ds2  user_1 user_2
          actual-data-nodes: ds$->{1..2}.user_$->{1..2}
#          key-generator:
#            column: id
#            type: SNOWFLAKE
          # 分表策略
          table-strategy:
            inline:
              # 分表列
              sharding-column: id
              # 分表算法  id 偶数存储到 user_1 奇数存储到 user_2
              # 除2取余数 要么是0要么是1 然后给+1 对应的就是user_1 user_2
              algorithm-expression: user_$->{id % 2 + 1}
          database-strategy: # 个性化指定某个表(user)的分库策略
            inline:
              # 分库列
              sharding-column: client_id
              # 分库算法  client_id 偶数存储到 ds1 奇数存储到 ds2
              # 除2取余数 要么是0要么是1 然后给+1 对应的就是ds1 ds2
              algorithm-expression: ds$->{client_id % 2 + 1}

    props:
      # 打印SQL日志
      sql:
        show: true     
复制代码
说明:
	与水平分表相比, 只是额外配置多配置了一个数据源(ds2)以及 user 表的 分库策略 (database-strategy)

测试结果

奇数测试

insert_client2_id1:插入 clientId 为 2、id 为 1 的数据

java 复制代码
    @Test
    void insert_client2_id1() {
        User user = new User();
        user.setId(1);
        user.setName("user_" + 1);
        user.setClientId(2);
        user.setAge(18);
        userMapper.insert(user);
    }
  • 运行结果
  1. clientId 为 2,根据奇偶策略,偶数应存储到库 ds1(sharding_demo-1)
  2. id 为 1,根据奇偶策略,奇数应存储到表 user_2
  3. 最终存储到 sharding_demo-1 库 的 user_2 表


复制代码
说明:
	日志中也可以看出,使用的是ds1(sharding_demo-1)插入的表为 user_2

偶数测试

insert_client1_id2:插入 clientId 为 1、id 为 2 的数据

java 复制代码
    @Test
    void insert_client1_id2() {
        User user = new User();
        user.setId(2);
        user.setName("user_" + 2);
        user.setClientId(1);
        user.setAge(20);
        userMapper.insert(user);
    }
  • 运行结果
  1. clientId 为 1,根据奇偶策略,偶数应存储到库 ds2(sharding_demo-2)
  2. id 为 2,根据奇偶策略,奇数应存储到表 user_1
  3. 最终存储到 sharding_demo-2 库 的 user_1 表
复制代码
说明:
	日志中也可以看出,使用的是ds2(sharding_demo-2)插入的表为 user_1

查询测试

selectById

  1. 查询 id为1 且 clientId为2 的记录
  2. 查询 id为2 且 clientId为1 的记录
java 复制代码
    @Test
    void selectById() {
        userMapper.selectOne(new QueryWrapper<User>().eq("id",1).eq("client_id",2));
        userMapper.selectOne(new QueryWrapper<User>().eq("id",2).eq("client_id",1));
    }
  • 运行日志

    说明:
    1. clientId = 2 且 id = 1, 数据库 ds1 (sharding_demo-1) ,查询的表为 user_2
    2. clientId = 1 且 id = 2, 数据库 ds2 (sharding_demo-2) ,查询的表为 user_1
    3. 查询和插入均遵守分表奇偶策略,完全正确 !!!

综上所述,ShardingSphere-ShardingJdbc-水平分库奇偶策略 Demo 则告一段落,希望对大家有所帮助!

相关推荐
南客先生13 天前
海量聊天消息处理:ShardingJDBC分库分表、ClickHouse冷热数据分离、ES复合查询方案、Flink实时计算与SpringCloud集成
java·clickhouse·elasticsearch·flink·springcloud·shardingjdbc
drebander4 个月前
监控与调试:性能优化的利器 — ShardingSphere
shardingsphere·监控
drebander4 个月前
分布式 ID 生成策略:应用场景与 ShardingSphere 实现
分布式·shardingsphere
芝法酱4 个月前
芝法酱学习笔记(2.3)——shardingsphere分库分表
shardingsphere·分库分表
技术路上的苦行僧4 个月前
分布式专题(10)之ShardingSphere分库分表实战指南
分布式·shardingsphere·分库分表
ezreal_pan5 个月前
ShardingSphere-Proxy 连接实战:从 Golang 原生 SQL 到 GORM 的应用
golang·shardingsphere·分库分表
Cdaimadada5 个月前
ShardingSphere介绍
java·shardingsphere
战神刘玉栋5 个月前
《ShardingSphere 联邦查询分析》
shardingsphere
[email protected]9 个月前
IntelliJ IDEA 集成 ShardingSphere-JDBC 访问分库分表
ide·intellij-idea·shardingsphere·分库分表