Sharding-JDBC + MyBatisPlus 实现分库分表
前言
随着业务数据的增加,单个数据库服务器已经难以满足业务需要,必须考虑数据库集群的方式来提升性能。高性能数据库集群的第一种方式是“读写分离”,第二种方式是“数据库分片”。
Sharding-jdbc 作为成熟的分库分表技术框架,在国内应用广泛。本文将介绍基于 Sharding-JDBC + MyBatisPlus 的分库分表。
准备数据库
在一个或两个 MySQL 服务上创建两个数据库(test),执行下面的脚本创建三个订单表(t_order、t_order_0、t_order_1)。
t_order 只是为了 MybatisPlus 逆向生成 CRUD 代码(Mapper、Service),生成完代码可以删掉。
t_order_0 和 t_order_1 是保存订单数据的两个分表。
-- test.t_order_0 definition
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=986675951494496257 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
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=986675951494496257 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
引入 Maven 依赖
Maven 核心依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
demo 工程使用到的 Maven 依赖
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.phixlin</groupId>
<artifactId>sharding-sphere-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
<version>8.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringBoot 配置文件
spring:
shardingsphere:
datasource:
# 数据源
names: m0,m1
m0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
m1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test-node?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
rules:
sharding:
# 分片算法
sharding-algorithms:
# t-order 数据库
t-order-database-inline:
# 分片算法类型
type: INLINE
props:
# 分片算法的行表达式
algorithm-expression: m$->{ user_id % 2}
# t-order 表
t-order-inline:
type: INLINE
props:
algorithm-expression: t_order_$->{order_id % 2}
# 主键生成策略
key-generators:
t-order-id-snowflake:
type: SNOWFLAKE
props:
worker-id: 001
tables:
t_order:
# 由数据源名 + 表名组成(参考 Inline 语法规则)
actualDataNodes: m$->{0..1}.t_order_$->{0..1}
databaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: t-order-database-inline
# 表策略
tableStrategy:
# 用于单分片键的标准分片场景
standard:
# 分片列名称
shardingColumn: order_id
# 分片算法名称
shardingAlgorithmName: t-order-inline
# 主键策略
keyGenerateStrategy:
column: order_id
keyGeneratorName: t-order-id-snowflake
props:
sql-show: true
实体类
package cn.phixlin.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.*;
@Data
@ToString
@Builder
@TableName("t_order")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "order_id", type = IdType.AUTO)
private Long orderId;
private Integer userId;
private String description;
}
测试接口
package cn.phixlin;
import cn.phixlin.entity.Order;
import cn.phixlin.service.impl.OrderServiceImpl;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
@SpringBootTest
public class SampleTest {
@Autowired
private OrderServiceImpl orderService;
@Test
public void testAutoId() {
// 自动生成 order_id
Order order = Order.builder().userId(664).description("分库测试").build();
System.out.println(order);
orderService.save(order);
}
@Test
public void testSplit() {
Order order = Order.builder().orderId(888L).userId(666).description("分库测试").build();
System.out.println(order);
orderService.saveOrUpdate(order);
}
}
License:
CC BY 4.0