在大数据时代,随着业务数据量的不断增长,单一的数据库往往难以承载大规模的数据处理需求。数据库分片(Sharding)是一种有效的数据库扩展技术,通过将数据分布到多个数据库实例上,提高系统的性能和可扩展性。

ShardingSphere 是一款开源的分布式数据库中间件,可以帮助我们轻松实现数据库分片。

本文的目的是介绍如何快速上手使用 ShardingSphere 来实现 MySQL 数据库分片。

一、ShardingSphere 简介

ShardingSphereApache 基金会下的一个开源项目,提供分布式数据库中间件解决方案。ShardingSphere 已经在2020年4月16日从 Apache 孵化器毕业,成为 Apache 顶级项目。其主要功能包括数据分片(Sharding)、读写分离、分布式事务以及数据加密等。ShardingSphere 主要由三个核心组件组成:

  1. Sharding-JDBC:轻量级的 Java 框架,直接集成在应用程序中,提供数据库分片、读写分离等功能。需要在 spring boot 中集成,编写相关的配置。如果分片策略用默认的4种,那可以只改配置就好了。如果分片策略很特殊,可以通过实现抽象类,写自定义的方法进行分片分库。
  2. Sharding-Proxy:独立部署的数据库代理,支持所有兼容 MySQLPostgreSQL 协议的客户端。原来程序连接到这个代理就可以实现分片和分库。程序不需要任何改变。
  3. Sharding-Sidecar(Plan):云原生环境下的数据库代理,与 Kubernetes 等平台集成。

1.1 对比

Sharding-JDBCSharding-ProxySharding-Sidecar
数据库任意MySQL/PostgreSQLMySQL/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-JDBCShardingSphere 的第一个产品,也是 ShardingSphere 的前身。 它定位为轻量级 Java 框架,在 JavaJDBC层提供的额外服务。它使用客户端直连数据库,以 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 的工作原理

理解了配置后,我们需要知道它是如何“欺骗”应用程序的:

  1. SQL 解析: 你发送 SELECT * FROM t_order WHERE user_id = 1。ShardingSphere 解析出逻辑表名和分片键。
  2. SQL 路由: 根据算法计算出该数据在 ds1.t_order_0
  3. SQL 改写: 将逻辑表名替换为真实表名,改写为 SELECT * FROM t_order_0 ...
  4. SQL 执行: 发送到真实的 MySQL 节点执行。
  5. 结果归并: 如果是跨库查询,它会将多个库的结果集进行合并、排序、分页后返回。

三、 实战中的注意事项

1. 广播表 (Broadcast Table)

有些表(如字典表、省份表)数据量小但每个分片库都需要用到。

  • 配置方式: broadcast-tables: [t_config]
  • 效果: 插入数据时会同步到所有库,查询时只查任意一个库。

2. 绑定表 (Binding Table)

如果 t_ordert_order_item 都是按 order_id 分片的,它们具有父子关系。

  • 优势: 告诉 ShardingSphere 它们是绑定的,在进行 Join 查询时,它会自动在同一个库内进行 Join,避免昂贵的跨库笛卡尔积。

3. 读写分离结合

ShardingSphere 完美支持在分片的基础上嵌套读写分离。你只需要在 rules 下再配置一个 readwrite-splitting 即可。


四、 这种方案的优缺点

优点缺点
透明化: 业务代码几乎不需要改动(支持 MyBatis, Hibernate)。复杂性: 配置较为繁琐,调试 SQL 路由较困难。
轻量: JDBC 版不需要部署服务器,无额外运维成本。限制: 不支持复杂的跨库外键、不支持部分特殊函数。
功能全: 自带影子库、数据加密、分布式事务集成。版本差异: 5.x 版本相比 4.x 配置变化非常大。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐