shardingshphere水平分片

可以分库分表也可以单独进行分表

依赖

父pom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mysql</groupId>
<artifactId>mysql</artifactId>
<name>mysql</name>
<packaging>pom</packaging>
<version>1.0.0</version>


<modules>
<module>ShardingSphereReadWrite</module>
<module>ShardingSphereVertical</module>
<module>ShardingSphereLevel</module>
</modules>

<properties>
<spring-boot.version>2.2.5.RELEASE</spring-boot.version>
<fastjson.version>1.2.62</fastjson.version>
<java.version>1.8</java.version>
<shardingsphere.version>5.1.2</shardingsphere.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
</properties>

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

</project>

pom

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?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>com.mysql</groupId>
<artifactId>mysql</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.example</groupId>
<artifactId>ShardingSphereLevel</artifactId>
<version>1.0.0</version>
<name>ShardingSphereLevel</name>
<description>ShardingSphereLevel</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>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

准备数据库和表

数据库1: localhost:3306

数据库2: localhost:3307

分别在两个数据库创建库和表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CREATE DATABASE db_order;

USE db_order;


CREATE TABLE t_order0 (
id BIGINT,
order_no VARCHAR(30),
user_id BIGINT,
amount DECIMAL(10,2),
PRIMARY KEY(id)
);

CREATE TABLE t_order1 (
id BIGINT,
order_no VARCHAR(30),
user_id BIGINT,
amount DECIMAL(10,2),
PRIMARY KEY(id)
);

创建完之后的样子

规则配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
spring:
application:
name: ShardingSphereLevel
shardingsphere:
datasource: # 配置数据源
server-order-0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/db_order
username: root
password: abc123
server-order-1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3307/db_order
username: root
password: abc123
names: server-order-0,server-order-1 # 所有数据源的名称,用逗号隔开
rules:
sharding:
sharding-algorithms: # 分片算法配置
alg_inline_userid: # 分片算法名称,自定义的名称
type: INLINE # 分片算法类型
props: # 分片算法属性配置
algorithm-expression: server-order-$->{user_id % 2} # 分片规则指定语句
table-inline: # 分片算法名称,自定义的名称
type: INLINE # 分片算法类型
props: # 分片算法属性配置
algorithm-expression: t_order$->{id % 2} # 分片规则指定语句
tables: # 分片表配置
t_order: # 表名
actual-data-nodes: server-order-$->{0..1}.t_order$->{0..1} # 真实的表名称,数据源.表名称,多个表之间用逗号隔开 可以这样写server-order-0.t_order0,server-order-0.t_order1,server-order-1.t_order0,server-order-1.t_order1
database-strategy: # 表分库策略
standard: # 标准分片策略
sharding-column: user_id # 分片的列名
sharding-algorithm-name: alg_inline_userid # 分片算法
table-strategy:
standard:
sharding-column: id # 分片的列名
sharding-algorithm-name: table-inline # 分片算法



props:
sql-show: true
mode:
type: Memory
repository:
type: JDBC

分库规则是

order表中user_id为偶数时,数据插入server-order0服务器user_id为奇数时,数据插入server-order1服务器。这样分片的好处是,同一个用户的订单数据,一定会被插入到同一台服务器上,查询一个用户的订单时效率较高。

分表的规则

order表中userId的为偶数时,数据插入对应服务器的t_order0表userId为奇数时,数据插入对应服务器的t_order1表

测试

运行test方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 水平分片:分表插入数据测试
*/
@Test
public void testInsertOrderTableStrategy(){

for (long i = 1; i < 5; i++) {

Order order = new Order();
order.setOrderNo("Sharding" + i);
order.setUserId(1L);
order.setAmount(new BigDecimal(100));
orderMapper.insert(order);
}

for (long i = 5; i < 9; i++) {

Order order = new Order();
order.setOrderNo("Sharding" + i);
order.setUserId(2L);
order.setAmount(new BigDecimal(100));
orderMapper.insert(order);
}
}

插入日志

1
2
3
4
5
6
7
8
9
10
11
12
2024-04-27 10:07:44.996  INFO 99540 --- [           main] ShardingSphere-SQL                       : Logic SQL: INSERT INTO t_order  ( id,
order_no,
user_id,
amount ) VALUES ( ?,
?,
?,
? )
2024-04-27 10:07:44.996 INFO 99540 --- [ main] ShardingSphere-SQL : SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2024-04-27 10:07:44.997 INFO 99540 --- [ main] ShardingSphere-SQL : Actual SQL: server-order-1 ::: INSERT INTO t_order0 ( id,
order_no,
user_id,
amount ) VALUES (?, ?, ?, ?) ::: [1784041711857569794, Sharding1, 1, 100]

查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
	/**
* 水平分片:查询所有记录
* 查询了两个数据源,每个数据源中使用UNION ALL连接两个表
*/
@Test
public void testShardingSelectAll(){
List<Order> orders = orderMapper.selectList(null);
orders.forEach(System.out::println);
}

/**
* 水平分片:根据user_id查询记录
* 查询了一个数据源,每个数据源中使用UNION ALL连接两个表
*/
@Test
public void testShardingSelectByUserId(){
QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
orderQueryWrapper.eq("user_id", 1L);
List<Order> orders = orderMapper.selectList(orderQueryWrapper);
orders.forEach(System.out::println);
}

日志

1
2
3
4
5
6
7
8
9
10
11
12
13
2024-04-27 10:10:33.485  INFO 2346 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT  id,order_no,user_id,amount  FROM t_order
2024-04-27 10:10:33.485 INFO 2346 --- [ main] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2024-04-27 10:10:33.485 INFO 2346 --- [ main] ShardingSphere-SQL : Actual SQL: server-order-0 ::: SELECT id,order_no,user_id,amount FROM t_order0 UNION ALL SELECT id,order_no,user_id,amount FROM t_order1
2024-04-27 10:10:33.485 INFO 2346 --- [ main] ShardingSphere-SQL : Actual SQL: server-order-1 ::: SELECT id,order_no,user_id,amount FROM t_order0 UNION ALL SELECT id,order_no,user_id,amount FROM t_order1
Order(id=1784041713484959746, orderNo=Sharding8, userId=2, amount=100.00)
Order(id=1784041713434628097, orderNo=Sharding5, userId=2, amount=100.00)
Order(id=1784041713459793921, orderNo=Sharding6, userId=2, amount=100.00)
Order(id=1784041713472376833, orderNo=Sharding7, userId=2, amount=100.00)
Order(id=1784041711857569794, orderNo=Sharding1, userId=1, amount=100.00)
Order(id=1784041713371713538, orderNo=Sharding2, userId=1, amount=100.00)
Order(id=1784041713392685058, orderNo=Sharding3, userId=1, amount=100.00)
Order(id=1784041713417850881, orderNo=Sharding4, userId=1, amount=100.00)

rules.sharding.sharding-algorithms.type参数主要用于指定分片算法的类型。以下是一些常见的 type 选项:

参数名称 参数描述
inline 行表达式分片算法。该算法允许你使用行表达式来定义分片规则,适用于简单的分片场景。
hint Hint 分片算法。该算法允许你使用 Hint 来指定分片规则,适用于一些特殊的分片场景。
mod_sharding 取模分片算法。根据指定的分片数量进行取模运算来进行分片,例如 user_id % 8
range_sharding 范围分片算法。允许你定义一个范围来进行分片,适用于范围查询等场景。
hash_sharding 哈希分片算法。根据指定的哈希算法进行分片,适用于一些需要一致性哈希的场景。

rules.sharding.tables.<logic_table_name>.table-strategy参数用来配置表分片的策略,可配置的属性如下:

1、standard:标准分片策略。

参数名称 参数描述
sharding-column 分片列名称
precise-algorithm-class-name 精确分片算法类名称,用于 = 和 IN 查询。
range-algorithm-class-name 范围分片算法类名称,用于 BETWEEN 查询。

2、complex:复合分片策略。

参数名称 参数描述
sharding-columns 分片列名称列表,多个列以逗号分隔。
algorithm-class-name 复合分片算法类名称。

3、inline:行表达式分片策略。

参数名称 参数描述
sharding-column 分片列名称。
algorithm-expression 分片算法行表达式,例如:${column} % 2。

4、hint:Hint 分片策略。

参数名称 参数描述
algorithm-class-name Hint分片算法类名称。

gitee地址


shardingshphere水平分片
https://zhaops-hub.github.io/2024/04/27/mysql/shardingsphere/shardingshphere水平分片/
作者
赵培胜
发布于
2024年4月27日
许可协议