大纲
前言
学习资源
ShardingSphere-Proxy 分布式序列算法
水平分片(包括水平分库和水平分表)需要关注分布式序列(即分布式全局唯一 ID),因为不能简单的使用基于数据库的自增主键,否则不同库不同表之间会发生主键冲突。通常主键冲突有两种解决方案:一种是使用 MyBatis-Plus 的 ID 生成策略;一种是使用 ShardingSphere-Proxy 的分布式序列配置。
MyBatis-Plus 的 ID 生成策略
- 使用 MyBatis-Plus 的 ID 生成策略
ASSIGN_ID(默认是基于 Snowflake 算法实现)
1 2 3 4 5 6 7 8 9 10 11 12
| @TableName("t_order") @Data public class Order {
@TableId(type = IdType.ASSIGN_ID) private Long id;
}
|
- 在 MyBatis-Plus 中,Snowflake 算法生成的 ID 是一个 64 位长整型(
| 1 bit 符号位 | 41 bit 时间戳 | 5 bit 数据中心 ID | 5 bit 工作机器 ID | 12 bit 序列号 |),其默认的 Snowflake 参数为:
| 参数 | | 默认值 | 说明 |
|---|
dataCenterId | | 1 | 数据中心 ID(0 ~ 31) |
workerId | | 1 | 工作机器 ID(0 ~ 31) |
- 在 MyBatis-Plus 中,Snowflake 参数的默认值在分布式部署时可能会出现 ID 冲突,因此通常需要自定义 Snowflake 参数(包括
dataCenterId 和 workerId),避免 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 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.core.toolkit.Sequence; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import java.net.InetAddress; import java.net.NetworkInterface;
@Configuration public class SnowflakeConfig {
@Bean public IdentifierGenerator identifierGenerator() { return new IdentifierGenerator() {
private final Sequence sequence = new Sequence(getWorkerId(), getDatacenterId());
@Override public Number nextId(Object entity) { return sequence.nextId(); }
}; }
private long getWorkerId() { try { String hostAddress = InetAddress.getLocalHost().getHostAddress(); return (hostAddress.hashCode() & 31); } catch (Exception e) { return 0; } }
private long getDatacenterId() { try { InetAddress inetAddress = InetAddress.getLocalHost(); NetworkInterface ni = NetworkInterface.getByInetAddress(inetAddress);
if (ni == null) { return 0; }
byte[] mac = ni.getHardwareAddress(); if (mac == null || mac.length == 0) { return 0; }
return (mac[mac.length - 1] & 31); } catch (Exception e) { return 0; } }
}
|
ShardingSphere 的分布式序列
ShardingSphere-Proxy 内置了两种分布式序列算法(即分布式 ID 生成算法),包括 SNOWFLAKE 和 UUID,可用于生成分布式全局唯一 ID。
SNOWFLAKE 算法
- 这里以单库分表举例,演示如何配置 ShardingSphere-Proxy 使用
SNOWFLAKE 分布式序列算法(有 DistSQL 和 YAML 两种配置方式,任选一种方式即可)
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
|
CREATE DATABASE sharding_db;
USE sharding_db;
ADD RESOURCE server_order0 ( URL="jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
CREATE SHARDING ALGORITHM alg_inline_order ( TYPE(NAME=INLINE, PROPERTIES( "algorithm-expression"="t_order${order_id % 2}" )) );
CREATE SHARDING KEY GENERATOR alg_snowflake ( TYPE(NAME=SNOWFLAKE, PROPERTIES( "max-vibration-offset"="1", "max-tolerate-time-difference-milliseconds"="10" )) );
CREATE SHARDING TABLE RULE t_order ( DATANODES("server_order0.t_order${0..1}"), TABLE_STRATEGY ( TYPE=STANDARD, SHARDING_COLUMN=order_id, SHARDING_ALGORITHM=alg_inline_order ), KEY_GENERATE_STRATEGY ( COLUMN=id, KEY_GENERATOR=alg_snowflake ) );
|
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
|
schemaName: sharding_db
dataSources: server_order0: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
rules: - !SHARDING tables: t_order: actualDataNodes: server_order0.t_order${0..1} tableStrategy: standard: shardingColumn: order_id shardingAlgorithmName: alg_inline_order keyGenerateStrategy: column: id keyGeneratorName: alg_snowflake shardingAlgorithms: alg_inline_order: type: INLINE props: algorithm-expression: t_order${order_id % 2} keyGenerators: alg_snowflake: type: SNOWFLAKE props: max-vibration-offset: 1 max-tolerate-time-difference-milliseconds: 10
|
- 此时,需要将实体类中的 MyBatis-Plus 的 ID 生成策略修改为
NONE:
1 2 3 4 5 6 7 8 9 10 11 12
| @TableName("t_order") @Data public class Order {
@TableId(type = IdType.NONE) private Long id;
}
|
- ShardingSphere-Proxy 的
SNOWFLAKE 分布式序列算法支持配置以下属性:
| 属性名称 | 数据类型 | 说明 | 默认值 |
|---|
max-vibration-offset | int | 最大抖动上限值,范围是 [0, 4096)。 注意:若使用此算法生成值作分片值(分片列的值),建议配置此属性。此算法在不同毫秒内所生成的 Key 取模 2^n(这里的 2^n 一般为分库或分表数量)之后结果总为 0 或 1。 该属性的作用是为了让同一毫秒生成的 ID,最终的分片取模结果不总是落在同一个库 / 表上,用于避免分片倾斜(热点分片)问题。 为防止上述分片问题,建议将此属性值配置为 (2^n) - 1。 | 1 |
max-tolerate-time-difference-milliseconds | long | 最大容忍时钟回退时间,单位:毫秒 | 10 |
SNOWFLAKE 分布式序列算法中,max-vibration-offset 属性的配置示例:
| 分库数量 | 2^n | max-vibration-offset 的建议值 (2^n) - 1 |
|---|
| 2 库 | 2¹=2 | 1 |
| 4 库 | 2²=4 | 3 |
| 8 库 | 2³=8 | 7 |
| 16 库 | 2⁴=16 | 15 |
| 32 库 | 2⁵=32 | 31 |
总结
在 ShardingSphere-Proxy 的 SNOWFLAKE 分布式序列算法中,max-vibration-offset 属性用来给 Snowflake ID 在同一毫秒内增加随机性,避免分片时总落到某几个库 / 表,防止热点库 / 表的出现。
UUID 算法
- 这里以单库分表举例,演示如何配置 ShardingSphere-Proxy 使用
UUID 分布式序列算法(有 DistSQL 和 YAML 两种配置方式,任选一种方式即可)
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
|
CREATE DATABASE sharding_db;
USE sharding_db;
ADD RESOURCE server_order0 ( URL="jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
CREATE SHARDING ALGORITHM alg_inline_order ( TYPE(NAME=INLINE, PROPERTIES( "algorithm-expression"="t_order${order_id % 2}" )) );
CREATE SHARDING KEY GENERATOR alg_uuid ( TYPE(NAME=UUID) );
CREATE SHARDING TABLE RULE t_order ( DATANODES("server_order0.t_order${0..1}"), TABLE_STRATEGY ( TYPE=STANDARD, SHARDING_COLUMN=order_id, SHARDING_ALGORITHM=alg_inline_order ), KEY_GENERATE_STRATEGY ( COLUMN=id, KEY_GENERATOR=alg_uuid ) );
|
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
|
schemaName: sharding_db
dataSources: server_order0: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
rules: - !SHARDING tables: t_order: actualDataNodes: server_order0.t_order${0..1} tableStrategy: standard: shardingColumn: order_id shardingAlgorithmName: alg_inline_order keyGenerateStrategy: column: id keyGeneratorName: alg_uuid shardingAlgorithms: alg_inline_order: type: INLINE props: algorithm-expression: t_order${order_id % 2} keyGenerators: alg_uuid: type: UUID
|
- 此时,需要将实体类中的 MyBatis-Plus 的 ID 生成策略修改为
NONE:
1 2 3 4 5 6 7 8 9 10 11 12
| @TableName("t_order") @Data public class Order {
@TableId(type = IdType.NONE) private String id;
}
|
ShardingSphere-Proxy 分片算法
分片算法的类型
ShardingSphere-Proxy 与 ShardingSphere-JDBC 在底层实现上使用同一套分布式序列算法实现,只是两者在配置与管理能力上并不完全一致,其中内置的分片算法如下所示:
自动分片算法
- 取模分片算法(
MOD)- 概述:对分片键取模,决定路由的库 / 表序号。
- 特点:算法简单、性能高、均匀分布。
- 适用场景:用户 ID、订单 ID 等数值型字段且写请求均匀分布的场景。
- 哈希取模分片算法(
HASH_MOD)- 概述:对分片键先做哈希,再取模。
- 特点:分布更均匀,避免 ID 递增导致热点。
- 适用场景:字符串类型分片键(如手机号、Email、UUID)。
- 基于分片容量的范围分片算法(
VOLUME_RANGE)- 概述:按单分片最大承载容量进行范围分片。
- 特点:按数据量增长自动落到不同库 / 表。
- 适用场景:数据量随时间增长、按容量控制每个分片大小(如日志类业务)。
- 基于分片边界的范围分片算法(
BOUNDARY_RANGE)- 概述:在配置中预先定义各分片的边界范围。
- 特点:控制精确,可与业务范围区间对应。
- 适用场景:省份编码、分等级、金额区间等明确范围的业务。
- 自动时间段分片算法(
AUTO_INTERVAL)- 概述:按时间自动生成分片,比如每天 / 每月自动建表。
- 特点:避免手动扩容,时间分片自动推进。
- 适用场景:日志表、订单表、流水表的按时间分表。
标准分片算法
- 行表达式分片算法(
INLINE)- 概述:使用 Groovy 表达式生成路由,如
t_order_$->{user_id % 4}。 - 特点:灵活、配置简单、可自定义表达式。
- 适用场景:分片条件规则清晰,可用简单表达式定义的场景。
- 时间范围分片算法(
INTERVAL)- 概述:通过时间区间计算应该路由到哪个时间分片。
- 特点:支持 “时间 → 表名” 的表达式映射。
- 适用场景:按年 / 月 / 天的时间序列数据分表(如日志、订单流水)。
复合分片算法
- 复合行表达式分片算法(
COMPLEX_INLINE)- 概述:支持多个分片键,通过表达式组合路由。
- 特点:多维条件路由,灵活性高。
- 适用场景:订单场景:需按
user_id、order_time 等联合多个键决定路由。
Hint 分片算法
- Hint 行表达式分片算法(
HINT_INLINE)- 概述:基于 Hint(SQL 注入式强制路由值)的表达式算法。
- 特点:程序员通过代码显式指定分片,不依赖 SQL 条件。
- 适用场景:
- SQL 本身没有分片字段(例如跨库 JOIN 时强制路由)
- 使用中间件或服务层统一指定分片键
- 灰度 / 运营类特殊请求
自定义类分片算法
ShardingSphere-Proxy 除了提供内置的分片算法,还支持开发者自定义类分片算法(CLASS_BASED),可通过配置分片策略类型和算法类名,实现自定义扩展。
分片算法的使用
特别注意
ShardingSphere-Proxy 内置的分片算法同时适用于垂直分片(垂直分库、垂直分表)和水平分片(水平分库、水平分表)。由于篇幅限制,下面仅给出部分分片算法的配置示例。无论 ShardingSphere-Proxy 是使用 YAML 配置 还是 DistSQL 配置,都必须注意 ShardingSphere-Proxy 的版本差异。不同版本之间支持的 DistSQL 命令、YAML 配置语法以及参数格式可能存在较大差异,同一份配置在不同版本下可能无法直接执行或行为不一致,因此在编写和迁移配置时必须结合 ShardingSphere-Proxy 具体版本进行验证。
水平分库
这里以水平分库为例子,演示如何使用 ShardingSphere-Proxy 提供的分片算法进行分库。
分库规则:
t_order 逻辑表中 user_id 为偶数时,数据插入到订单数据库服务器一(server_order0);user_id 为奇数时,数据插入到订单数据库服务器二(server_order1)。- 这样分库的好处是,同一个用户的订单数据,一定会被插入到同一台数据库服务器上,这样查询某个用户的所有订单时效率较高。
- 值得一提的,由于这里每个库只有一张表,所以只需要配置分库策略(
DATABASE_STRATEGY),不需要配置分表策略(TABLE_STRATEGY)。
数据结构:
1 2 3 4
| server_order0 └── t_order server_order1 └── t_order
|
行表达式分片算法
YAML 配置模式
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
| schemaName: sharding_db
dataSources: server_order0: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
server_order1: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
rules: - !SHARDING tables: t_order: actualDataNodes: server_order${0..1}.t_order databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: alg_inline_userid shardingAlgorithms: alg_inline_userid: type: INLINE props: algorithm-expression: server_order${user_id % 2}
|
DistSQL 配置模式
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
| CREATE DATABASE sharding_db;
USE sharding_db;
ADD RESOURCE server_order0 ( URL="jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
ADD RESOURCE server_order1 ( URL="jdbc:mysql://192.168.2.191:3311/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
CREATE SHARDING ALGORITHM alg_inline_userid ( TYPE(NAME=INLINE, PROPERTIES( 'algorithm-expression'='server_order${user_id % 2}' )) );
CREATE SHARDING TABLE RULE t_order ( DATANODES('server_order${0..1}.t_order'), DATABASE_STRATEGY ( TYPE=STANDARD, SHARDING_COLUMN=user_id, SHARDING_ALGORITHM=alg_inline_userid ) );
|
取模分片算法
YAML 配置模式
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
| schemaName: sharding_db
dataSources: server_order0: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
server_order1: url: jdbc:mysql://192.168.2.191:3311/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
rules: - !SHARDING tables: t_order: actualDataNodes: server_order${0..1}.t_order databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: alg_mod shardingAlgorithms: alg_mod: type: MOD props: sharding-count: 2
|
DistSQL 配置模式
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
| CREATE DATABASE sharding_db;
USE sharding_db;
ADD RESOURCE server_order0 ( URL="jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
ADD RESOURCE server_order1 ( URL="jdbc:mysql://192.168.2.191:3311/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
CREATE SHARDING ALGORITHM alg_mod ( TYPE(NAME=MOD,PROPERTIES( "sharding-count"="2" )) );
CREATE SHARDING TABLE RULE t_order ( DATANODES("server_order${0..1}.t_order"), DATABASE_STRATEGY( TYPE=STANDARD, SHARDING_COLUMN=user_id, SHARDING_ALGORITHM=alg_mod ) );
|
哈希取模分片算法
YAML 配置模式
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
| schemaName: sharding_db
dataSources: server_order0: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
server_order1: url: jdbc:mysql://192.168.2.191:3311/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
rules: - !SHARDING tables: t_order: actualDataNodes: server_order${0..1}.t_order databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: alg_hash_mod shardingAlgorithms: alg_hash_mod: type: HASH_MOD props: sharding-count: 2
|
DistSQL 配置模式
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
| CREATE DATABASE sharding_db;
USE sharding_db;
ADD RESOURCE server_order0 ( URL="jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
ADD RESOURCE server_order1 ( URL="jdbc:mysql://192.168.2.191:3311/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
CREATE SHARDING ALGORITHM alg_hash_mod ( TYPE(NAME=HASH_MOD,PROPERTIES( "sharding-count"="2" )) );
CREATE SHARDING TABLE RULE t_order ( DATANODES("server_order${0..1}.t_order"), DATABASE_STRATEGY( TYPE=STANDARD, SHARDING_COLUMN=user_id, SHARDING_ALGORITHM=alg_hash_mod ) );
|
水平分表
这里以水平分表为例子,演示如何使用 ShardingSphere-Proxy 提供的分片算法进行分表。由于篇幅有限,这里仅介绍哈希取模分片算法的使用,其他分片算法可以参考上面 水平分库 的使用。
分表规则:
t_order 逻辑表中 order_no 的哈希值为偶数时,数据插入对应数据库服务器的 t_order0 表;order_no 的哈希值为奇数时,数据插入对应数据库服务器的 t_order1 表。- 值得一提的是,由于这里只有一个数据库(即单库分表),所以只需要配置分表策略(
TABLE_STRATEGY),不需要配置分库策略(DATABASE_STRATEGY)。 - 因为
order_no 是字符串类型,所以不能直接取模,需要对其进行哈希计算再取模。
数据结构:
1 2 3
| server_order0 ├── t_order0 └── t_order1
|
哈希取模分片算法
YAML 配置模式
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
| schemaName: sharding_db
dataSources: server_order0: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
rules: - !SHARDING tables: t_order: actualDataNodes: server_order0.t_order${0..1} tableStrategy: standard: shardingColumn: order_no shardingAlgorithmName: alg_hash_mod shardingAlgorithms: alg_hash_mod: type: HASH_MOD props: sharding-count: 2
|
DistSQL 配置模式
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
| CREATE DATABASE sharding_db;
USE sharding_db;
ADD RESOURCE server_order0 ( URL="jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
CREATE SHARDING ALGORITHM alg_hash_mod ( TYPE(NAME=HASH_MOD,PROPERTIES( "sharding-count"="2" )) );
CREATE SHARDING TABLE RULE t_order ( DATANODES("server_order0.t_order${0..1}"), TABLE_STRATEGY( TYPE="STANDARD", SHARDING_COLUMN="order_no", SHARDING_ALGORITHM="alg_hash_mod" ) );
|
水平分库与水平分表
这里以水平分库 + 水平分表为例子,演示如何使用 ShardingSphere-Proxy 提供的分片算法。
分库规则:
t_order 逻辑表中 user_id 为偶数时,数据插入到订单数据库服务器一(server_order0);user_id 为奇数时,数据插入到订单数据库服务器二(server_order1)。- 这样分库的好处是,同一个用户的订单数据,一定会被插入到同一台数据库服务器上,这样查询某个用户的所有订单时效率较高。
分表规则:
t_order 逻辑表中 order_no 的哈希值为偶数时,数据插入对应数据库服务器的 t_order0 表;order_no 的哈希值为奇数时,数据插入对应数据库服务器的 t_order1 表。- 因为
order_no 是字符串类型,所以不能直接取模,需要对其进行哈希计算再取模。
数据结构:
1 2 3 4 5 6
| server_order0 ├── t_order0 └── t_order1 server_order1 ├── t_order0 └── t_order1
|
YAML 配置模式
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
| schemaName: sharding_db
dataSources: server_order0: url: jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
server_order1: url: jdbc:mysql://192.168.2.191:3311/db_order?serverTimezone=UTC&useSSL=false username: root password: 123456 connectionTimeoutMilliseconds: 30000 idleTimeoutMilliseconds: 60000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 1
rules: - !SHARDING tables: t_order: actualDataNodes: server_order${0..1}.t_order${0..1} databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: alg_mod tableStrategy: standard: shardingColumn: order_no shardingAlgorithmName: alg_hash_mod shardingAlgorithms: alg_mod: type: MOD props: sharding-count: 2 alg_hash_mod: type: HASH_MOD props: sharding-count: 2
|
DistSQL 配置模式
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 60 61 62 63 64 65 66 67
| CREATE DATABASE sharding_db;
USE sharding_db;
ADD RESOURCE server_order0 ( URL="jdbc:mysql://192.168.2.191:3310/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
ADD RESOURCE server_order1 ( URL="jdbc:mysql://192.168.2.191:3311/db_order?serverTimezone=UTC&useSSL=false", USER=root, PASSWORD=123456, PROPERTIES( "connectionTimeoutMilliseconds"="30000", "idleTimeoutMilliseconds"="60000", "maxLifetimeMilliseconds"="1800000", "maxPoolSize"="50", "minPoolSize"="1" ) );
CREATE SHARDING ALGORITHM alg_mod ( TYPE(NAME=MOD,PROPERTIES( "sharding-count"="2" ) ) );
CREATE SHARDING ALGORITHM alg_hash_mod ( TYPE(NAME=HASH_MOD,PROPERTIES( "sharding-count"="2" ) ) );
CREATE SHARDING TABLE RULE t_order ( DATANODES("server_order${0..1}.t_order${0..1}"), DATABASE_STRATEGY( TYPE=STANDARD, SHARDING_COLUMN=user_id, SHARDING_ALGORITHM=alg_mod ), TABLE_STRATEGY( TYPE=STANDARD, SHARDING_COLUMN=order_no, SHARDING_ALGORITHM=alg_hash_mod ) );
|