跳至主要內容

01. shardingsphere

chanchaw大约 5 分钟编程语言数据库mysql中间件

概述

使用 ShardingSphere 对MYSQL进行分库分表试验,创建的是 Springboot 项目,数据库位于本地的 lagou1 和 云服务器的 lagou2 ,其中的表结构都一样,没有使用 mybatis 转而使用了 jpa。要说明的是创建数据库时指定了主键是自增的但是在 springboot 项目中插入数据时也是可以手动指定主键的,并不会报错,注意要将 mode 的主键字段的注解 @GeneratedValue(strategy = GenerationType.IDENTITY) 注释掉。 本文是跟随拉勾的MYSQL视频试验分库分表的做法,使用了 ShardingSphere,测试用数据的建表语句如下

-- auto-generated definition
CREATE TABLE position (
    Id     BIGINT(11) AUTO_INCREMENT PRIMARY KEY,
    name   VARCHAR(256) NULL,
    salary VARCHAR(50)  NULL,
    city   VARCHAR(256) NULL
)
    CHARSET = utf8mb4;



-- auto-generated definition
CREATE TABLE position_detail (
    id          BIGINT(11) AUTO_INCREMENT PRIMARY KEY,
    pid         BIGINT(11) DEFAULT 0 NOT NULL,
    description TEXT                 NULL
)
    CHARSET = utf8mb4;

-- b_order 建表脚本
-- auto-generated definition
CREATE TABLE b_order (
    id              BIGINT AUTO_INCREMENT PRIMARY KEY,
    is_del          BIT          DEFAULT b'0'              NULL COMMENT '默认0表示有效,1表示被删除',
    company_id      INT          DEFAULT 0                 NULL COMMENT '公司ID',
    position_id     INT          DEFAULT 0                 NULL COMMENT '职位ID',
    user_id         INT          DEFAULT 0                 NULL COMMENT '用户ID',
    publish_user_id INT          DEFAULT 0                 NULL COMMENT '职位发布者ID',
    resume_type     INT          DEFAULT 0                 NULL COMMENT '默认0表示简历类型是附件,1表示在线',
    status          VARCHAR(256) DEFAULT ''                NULL COMMENT '投递状态',
    create_time     DATETIME     DEFAULT CURRENT_TIMESTAMP NULL,
    operate_time    DATETIME     DEFAULT CURRENT_TIMESTAMP NULL COMMENT '操作时间',
    work_year       VARCHAR(100) DEFAULT ''                NULL COMMENT '工作年限',
    name            VARCHAR(256) DEFAULT ''                NULL COMMENT '投递简历人名字',
    position_name   VARCHAR(256) DEFAULT ''                NULL COMMENT '职位名称',
    resumeId        INT          DEFAULT 0                 NULL COMMENT '投递的简历ID'
) COMMENT '分库分表试验';


-- auto-generated definition
CREATE TABLE c_order (
    id              BIGINT AUTO_INCREMENT PRIMARY KEY,
    user_id         INT          DEFAULT 0                 NULL COMMENT '用户ID',
    is_del          BIT          DEFAULT b'0'              NULL,
    company_id      INT          DEFAULT 0                 NULL COMMENT '公司ID',
    publish_user_id INT          DEFAULT 0                 NULL COMMENT 'B端用户ID',
    position_id     INT          DEFAULT 0                 NULL COMMENT '职位ID',
    resume_type     INT          DEFAULT 0                 NULL COMMENT '简历类型0表示附件,1为在线',
    status          VARCHAR(256) DEFAULT ''                NULL,
    create_time     DATETIME     DEFAULT CURRENT_TIMESTAMP NULL,
    update_time     DATETIME     DEFAULT CURRENT_TIMESTAMP NULL
);

JPA最简示例

依赖版本号

Springboot 版本号

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

JPA依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

JPA模型类使用到的注解

下面是一个简单的模型类的案例,可以看到最简使用的注解

package com.xdf.sharding.model;

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name="position")
public class Position implements Serializable {
    @Id
    @Column(name="id")
    // 表示自增主键,后面在手动添加数据的时候就不能设置主键值了
    // 这里要注释掉以后添加数据时手动指定主键,那么以后就可以使用UUID
    // 或者雪花片的方式指定主键达到分布式的效果
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(name="name")
    private String name;
    @Column(name="salary")
    private String salary;
    @Column(name="city")
    private String city;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSalary() {
        return salary;
    }

    public void setSalary(String salary) {
        this.salary = salary;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Position{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", salary='" + salary + '\'' +
                ", city='" + city + '\'' +
                '}';
    }
}

制作 DAO - Repository

package com.xdf.sharding.dao;

import com.xdf.sharding.model.Position;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.math.BigInteger;

public interface PositionRepository extends JpaRepository<Position,Long> {

    @Query(nativeQuery = true,value="select p.id,p.name,pd.description from position p left join position_detail pd on p.id=pd.pid where p.id=:id")
    public Object findPositionByid(@Param("id") long id);
}

上面案例中制作了自定义查询的方法,此时已经有增删改查等基本操作功能,使用 positionRepository.save(instance) 保存数据到表中,上面声明接口时泛型中指定的 Position 对应模型类的名称,后面的 Long 是标主键的数据类型

测试手动设置自增主键

  • 将 model 下的 Position 的主键字段 id 上的注解 [@GeneratedValue(strategy ](/GeneratedValue(strategy ) = GenerationType.IDENTITY) 注释掉,该注解是使用雪花片分布式主键(或者UUID方式)时 ShardingSphere 使用的
  • 可以通过 for 循环的方式手动填写实体对象的主键

测试雪花片分布式主键

  • 将 model 包下的Position 的主键字段 id 上的注解 [@GeneratedValue(strategy ](/GeneratedValue(strategy ) = GenerationType.IDENTITY)  启用
  • 设置配置文件  application-sharding-database.properties 中添加两行配置
# 使用雪花片的方式由 shrdingsphere 自动生成主键
spring.shardingsphere.sharding.tables.position.key-generator.column=id
spring.shardingsphere.sharding.tables.position.key-generator.type=SNOWFLAKE
  • 第一行表示表 position 的字段 id 是主键,第二行表示使用雪花片类型的分布式主键,因为数据库中设置了字段 id 是整数类型所以这里使用了雪花片方式

制作自定义主键生成器

  • 制作包 id
  • 制作类 MyDistId,并且实现接口 ShardingKeyGenerator
  • 在 resources 下制作目录 META-INF/services ,注意这里是两层目录
  • 在上面创建的目录 services 下创建名称为 org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator 的文件,在其中写入实现自定义主键的类的全限定名(即包名+类名称) com.xdf.sharding.id.MyDistId
  • 然后修改配置文件 application-sharding-database.properties 中的雪花片行为
# 下面的 ccDistKey 是自定义的分布式主键的类型名称
# 原本使用的是 SNOWFLAKE
spring.shardingsphere.sharding.tables.position.key-generator.type=ccDistKey

主从分库

关于 shardingsphere 的配置文件 D:\software\ideaProjs\sharding\src\main\resources\application-sharding-database.properties 中关于主从一起分库的配置如下图 shardingsphere01

分库的同时分表

本案例是拿表 b_order 首先分库到 ds0 和 ds1 两个数据库(即两个服务器),按照B端客户的编号平均分配到两个服务器上,同时每个服务器上又做分表,将 b_order 的数据分配到 b_order1 和 b_order2 中,相关的配置文件如下图 shardingsphere02