什么是 ShardingSphere?
Apache ShardingSphere 是一个开源的分布式数据库中间件生态圈,可以看作是一个数据库增强工具或中间件,它在应用程序和数据库之间,帮助开发者实现一些复杂的分布式数据库管理功能,为用户提供数据分片、分布式事务、数据库治理等功能。它支持通过分片(Sharding)、读写分离、影子库(Shadow Database)等多种方式,帮助开发者优化分布式数据库的操作体验。
具体来说,ShardingSphere 是为分布式数据库场景设计的,可以认为它是数据库能力的补充和增强。它并不直接存储数据,而是通过对 SQL 的拦截和处理,将数据分发到不同的数据库实例或表中,最终返回聚合的查询结果。
ShardingSphere 主要包括以下三个核心组件:
-
ShardingSphere-JDBC
-
类似于增强版的 JDBC,轻量级,无需中间层部署。
-
与应用程序嵌入在一起,支持数据分片、读写分离等功能。
-
-
ShardingSphere-Proxy
-
一个独立的代理层,类似数据库代理服务器。
-
可以直接与现有的数据库客户端(如 MySQL 客户端)交互,提供透明的数据分片和读写分离功能。
-
-
ShardingSphere-Scaling
-
提供数据迁移和同步服务,支持动态扩缩容。
-
关键点
逻辑表 vs. 物理表
-
逻辑表:应用程序中操作的表名。
-
物理表:实际存储数据的表名(通过 ShardingSphere 映射)。
分片策略
-
水平分片:根据分片键值(如
user_id
),将数据存储到不同的物理表。 -
库表映射规则:通过
actual-data-nodes
定义。
分布式 ID
-
使用
SNOWFLAKE
作为主键生成器,避免 ID 冲突。
路由和聚合
-
ShardingSphere 自动处理查询路由和结果聚合,开发者无需关心具体表的细节。
优势
轻量级:可以嵌入到应用中,不需要额外部署服务(使用 ShardingSphere-JDBC)。
扩展性强:支持动态添加数据源和分片规则。
支持多种数据库:如 MySQL、PostgreSQL、Oracle 等。
高性能:通过分片、读写分离优化性能。
兼容性:完全兼容现有的 JDBC 和数据库客户端。
注意点
-
Sharding 和事务冲突:
-
Sharding 会将数据分散到多个库表,普通的事务管理可能失效,需要使用分布式事务管理。
-
-
分片键的选择:
-
分片键应该是查询频繁的字段,避免影响性能。
-
-
规则复杂度:
-
复杂的分片规则可能导致维护成本增加,需要权衡业务需求。
-
与数据库的关系
功能 | 数据库提供 | ShardingSphere 提供 |
---|---|---|
数据存储 | 数据库(MySQL、PostgreSQL 等) | 不负责存储数据,仅负责分发、路由和聚合 |
SQL 执行 | 数据库 | 拦截 SQL,优化分片后的路由逻辑 |
分库分表 | 不支持或需手动实现 | 自动完成数据分片 |
读写分离 | 需手动配置 | 动态路由到主库/从库 |
分布式事务 | 复杂且需额外工具 | 内置分布式事务协议,简化实现 |
动态扩缩容 | 数据库不负责 | ShardingSphere-Scaling 提供支持 |
应用场景
数据分片(Sharding)
-
将大表拆分成多个小表(水平分表),分布到不同的数据库中。
-
提高查询性能,解决单表数据量过大的问题。
读写分离
-
配置主从数据库架构,将写操作路由到主数据库,读操作路由到从数据库。
-
提高数据库性能和吞吐量。
分布式事务
-
通过 XA、BASE 等事务协议,支持跨多个数据库的分布式事务管理。
多租户
-
在 SaaS 系统中,按租户划分数据,通过动态分表和路由实现隔离。
数据库治理
-
动态数据路由、灰度发布、数据脱敏等场景。
结合Spring Boot使用
1. 引入依赖
在 pom.xml
中添加 ShardingSphere 的依赖:
<dependencies>
<!-- ShardingSphere-JDBC 核心依赖 -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.3.1</version>
</dependency>
</dependencies>
2. 配置数据源
在 application.yml
文件中配置数据源和 ShardingSphere 规则:
spring:
shardingsphere:
datasource:
common:
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置第一个数据源
ds0:
url: jdbc:mysql://localhost:3306/demo_ds_0?useSSL=false&serverTimezone=UTC
# 配置第二个数据源
ds1:
url: jdbc:mysql://localhost:3306/demo_ds_1?useSSL=false&serverTimezone=UTC
rules:
sharding:
tables:
# 配置逻辑表 user
user:
actual-data-nodes: ds${0..1}.user_${0..1} # 定义物理表
table-strategy:
inline:
sharding-column: user_id # 分片键
algorithm-expression: user_${user_id % 2} # 分片算法
key-generator:
column: user_id
type: SNOWFLAKE
default-database-strategy:
inline:
sharding-column: user_id
algorithm-expression: ds${user_id % 2}