使用shardingsphere实现mysql数据库分片
在大数据时代,随着业务数据量的不断增长,单一的数据库往往难以承载大规模的数据处理需求。数据库分片(Sharding)是一种有效的数据库扩展技术,通过将数据分布到多个数据库实例上,提高系统的性能和可扩展性。
ShardingSphere 是一款开源的分布式数据库中间件,可以帮助我们轻松实现数据库分片。
本文的目的是介绍如何快速上手使用 ShardingSphere 来实现 MySQL 数据库分片。
一、ShardingSphere 简介
ShardingSphere 是 Apache 基金会下的一个开源项目,提供分布式数据库中间件解决方案。ShardingSphere 已经在2020年4月16日从 Apache 孵化器毕业,成为 Apache 顶级项目。其主要功能包括数据分片(Sharding)、读写分离、分布式事务以及数据加密等。ShardingSphere 主要由三个核心组件组成:
- Sharding-JDBC:轻量级的 Java 框架,直接集成在应用程序中,提供数据库分片、读写分离等功能。需要在
spring boot中集成,编写相关的配置。如果分片策略用默认的4种,那可以只改配置就好了。如果分片策略很特殊,可以通过实现抽象类,写自定义的方法进行分片分库。 - Sharding-Proxy:独立部署的数据库代理,支持所有兼容
MySQL、PostgreSQL协议的客户端。原来程序连接到这个代理就可以实现分片和分库。程序不需要任何改变。 - Sharding-Sidecar(Plan):云原生环境下的数据库代理,与
Kubernetes等平台集成。
1.1 对比
| Sharding-JDBC | Sharding-Proxy | Sharding-Sidecar | |
|---|---|---|---|
| 数据库 | 任意 | MySQL/PostgreSQL | MySQL/PostgreSQL |
| 连接消耗数 | 高 | 低 | 高 |
| 异构语言 | 仅Java | 任意 | 任意 |
| 性能 | 损耗低 | 损耗略高 | 损耗低 |
| 无中心化 | 是 | 否 | 是 |
| 静态入口 | 无 | 有 | 无 |
1.2 核心概念
分库分表中最重要的核心概念有两个,即路由键和分片算法,这两个将决定数据分片的位置,先稍微解释一下这两个概念:
-
路由键:也被称为分片键,也就是作为数据分片的基准字段,可以是一个或多个字段组成。
-
分片算法:基于路由键做一定逻辑处理,从而计算出一个最终节点位置的算法。
举个例子来感受一下,好比按 user_id 将用户表数据分片,每八百万条数据划分一张表,那在这里,user_id 就是路由键,而按user_id做范围判断则属于分片算法,一张表中的所有数据都会依据这两个基础,后续对所有的读写SQL进行改写,从而定位到具体的库、表位置。

在Sharding-Sphere这套技术中,无论是JDBC还是Proxy产品,工作的流程都遵循上述这个原则,里面除开上面介绍的路由键和分片算法的概念外,还有逻辑表、真实表、数据节点这三个概念:
-
逻辑表:提供给应用程序操作的表名,程序可以像操作原本的单表一样,灵活的操作逻辑表。
-
真实表:在各个数据库节点上真实存在的物理表,但表名一般都会和逻辑表存在偏差。
-
数据节点:主要是用于定位具体真实表的库表名称,如DB1.tb_user1、DB2.tb_user2…
-
均匀分布:指一张表的数量在每个数据源中都是一致的。
-
自定义分布:指一张表在每个数据源中,具体的数量由自己来定义,上图就是一种自定义分布。
以 Java 程序为例,编写业务代码时写的 SQL 语句,会直接基于逻辑表进行操作,逻辑表并不是一种真实存在的表结构,而是提供给 Sharding-Sphere 使用的,当 Sharding-Sphere 接收到一条操作某张逻辑表的 SQL语句时,它会根据已配置好的路由键和分片算法,对相应的 SQL语句进行解析,然后计算出 SQL要落入的数据节点,最后再将语句发给具体的真实表上处理即可。
二、ShardingSphere-JDBC
Sharding-JDBC是 ShardingSphere 的第一个产品,也是 ShardingSphere 的前身。 它定位为轻量级 Java 框架,在 Java 的 JDBC层提供的额外服务。它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。
Apache ShardingSphere-JDBC 可以通过Java 和 YAML 这 2 种方式进行配置,开发者可根据场景选择适合的配置方式。
2.2 原理
Sharding-JDBC 中的路由结果是通过分片字段和分片方法来确定的,如果查询条件中有 id 字段的情况还好,查询将会落到某个具体的分片
如果查询没有分片的字段,会向所有的db或者是表都会查询一遍,让后封装结果集给客户端。

接下来会搭建一个简单的SpringBoot+MyBatis项目,结合Sharding-Sphere-JDBC实现水平分库~
一、 核心配置五部曲 (Spring Boot 版)
使用 Apache ShardingSphere 实现 MySQL 分片是目前业界最主流的方案。它分为 ShardingSphere-JDBC(集成在代码中)和 ShardingSphere-Proxy(独立中间件)两种模式。
对于 Java 开发者,ShardingSphere-JDBC 更加常用,因为它性能损耗极低,且不需要额外维护中间件集群。
<!-- 分表分库依赖 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.2.1</version>
</dependency>
要实现分片,主要通过 application.yaml 配置以下五个核心要素:
1. 定义数据源 (Data Sources)
首先需要声明所有真实的物理数据库连接。
shardingsphere:
datasource:
names: ds0, ds1
ds0: # 数据库 A
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://localhost:3306/db_0
username: root
password: password
ds1: # 数据库 B
type: com.zaxxer.hikari.HikariDataSource
jdbc-url: jdbc:mysql://localhost:3306/db_1
username: root
password: password
2. 配置逻辑表与真实表 (Actual Data Nodes)
逻辑表是你在代码里写的表名(如 t_order),真实表是数据库里实际存在的物理表(如 t_order_0)。
rules:
sharding:
tables:
t_order: # 逻辑表名
actual-data-nodes: ds$->{0..1}.t_order_$->{0..1}
# 表示数据分布在 ds0.t_order_0, ds0.t_order_1, ds1.t_order_0, ds1.t_order_1
3. 配置分片策略 (Sharding Strategy)
这是最关键的一步,决定数据去哪个库、哪张表。
database-strategy: # 分库策略
standard:
sharding-column: user_id
sharding-algorithm-name: database-inline
table-strategy: # 分表策略
standard:
sharding-column: order_id
sharding-algorithm-name: table-inline
4. 定义算法 (Algorithms)
指定具体的算法逻辑,例如使用内联表达式(Inline)。
sharding-algorithms:
database-inline:
type: INLINE
props:
algorithm-expression: ds$->{user_id % 2} # user_id 偶数进 ds0,奇数进 ds1
table-inline:
type: INLINE
props:
algorithm-expression: t_order_$->{order_id % 2} # order_id 偶数进 t_order_0
5. 分布式序列 (Key Generator)
配置全局唯一的主键生成策略,通常使用雪花算法。
key-generate-strategy:
column: order_id
key-generator-name: snowflake
key-generators:
snowflake:
type: SNOWFLAKE
二、 ShardingSphere 的工作原理
理解了配置后,我们需要知道它是如何“欺骗”应用程序的:
- SQL 解析: 你发送
SELECT * FROM t_order WHERE user_id = 1。ShardingSphere 解析出逻辑表名和分片键。 - SQL 路由: 根据算法计算出该数据在
ds1.t_order_0。 - SQL 改写: 将逻辑表名替换为真实表名,改写为
SELECT * FROM t_order_0 ...。 - SQL 执行: 发送到真实的 MySQL 节点执行。
- 结果归并: 如果是跨库查询,它会将多个库的结果集进行合并、排序、分页后返回。
三、 实战中的注意事项
1. 广播表 (Broadcast Table)
有些表(如字典表、省份表)数据量小但每个分片库都需要用到。
- 配置方式:
broadcast-tables: [t_config] - 效果: 插入数据时会同步到所有库,查询时只查任意一个库。
2. 绑定表 (Binding Table)
如果 t_order 和 t_order_item 都是按 order_id 分片的,它们具有父子关系。
- 优势: 告诉 ShardingSphere 它们是绑定的,在进行 Join 查询时,它会自动在同一个库内进行 Join,避免昂贵的跨库笛卡尔积。
3. 读写分离结合
ShardingSphere 完美支持在分片的基础上嵌套读写分离。你只需要在 rules 下再配置一个 readwrite-splitting 即可。
四、 这种方案的优缺点
| 优点 | 缺点 |
|---|---|
| 透明化: 业务代码几乎不需要改动(支持 MyBatis, Hibernate)。 | 复杂性: 配置较为繁琐,调试 SQL 路由较困难。 |
| 轻量: JDBC 版不需要部署服务器,无额外运维成本。 | 限制: 不支持复杂的跨库外键、不支持部分特殊函数。 |
| 功能全: 自带影子库、数据加密、分布式事务集成。 | 版本差异: 5.x 版本相比 4.x 配置变化非常大。 |
更多推荐
所有评论(0)