分库分表(Sharding)是应对海量数据存储和高并发访问的常用技术手段。当单机数据库的性能或存储达到瓶颈时,通过将数据分散到多个物理数据库或表中,从而提升系统的整体吞吐量。

为什么要分库分表?

  1. 单表性能瓶颈:随着数据量增大(如超过 500 万行或 2GB),索引 B+ 树层级加深,磁盘 IO 压力增大,查询性能显著下降。
  2. 单库并发瓶颈:单机数据库的连接数、IOPS、网络带宽等资源有限,难以支撑超高并发。
  3. 磁盘存储瓶颈:单机磁盘空间有限,无法容纳无限增长的数据。

拆分维度

1. 垂直拆分 (Vertical)

  • 垂直分库:按业务模块拆分。例如将用户表、订单表、商品表分别存放在不同的数据库实例中。核心是专库专用
  • 垂直分表:按字段拆分。将一张表中不常用的、或者占用空间大的字段(如 text 类型的描述信息)拆分到另一张扩展表中。核心是冷热分离

2. 水平拆分 (Horizontal)

行记录拆分。将同一个表的数据按某种规则分布到多个库或多个表中。

  • 水平分库:将单表数据分散到不同的数据库实例,解决单库并发和存储瓶颈。
  • 水平分表:将单表数据拆分为多张结构相同的表,解决单表性能瓶颈。

常见分片规则

规则实现方式优点缺点
Hash 取模hash(key) % n数据分布均匀扩容需数据迁移(可用一致性哈希优化)
范围 (Range)按 ID 范围或时间段扩容简单,无需迁移易产生热点问题(如新数据全写在最后一个分片)
映射表 (Lookup)独立存储映射关系灵活,支持任意逻辑增加额外网络开销,映射表本身易成瓶颈

带来的挑战与解决方案

  1. 分布式 ID:不能再依赖数据库自增 ID。需使用 Snowflake ID、UUID 或号段模式保证全局唯一。
  2. 跨节点 Join:无法直接在 SQL 中 Join。
    • 解决:应用层组装、字段冗余、或者是使用 ER 表(将有关系的表分布在同一分片)。
  3. 跨节点聚合count, order by, group by 等操作。
    • 解决:在各个分片并行执行后,由中间件或应用层进行结果合并 (Merge)
  4. 分布式事务:跨库操作无法保证 ACID。
    • 解决:使用两阶段提交 (2PC)、TCC、Saga 或本地消息表实现最终一致性。

常用中间件

  • 客户端代理ShardingSphere-JDBC (TDDL, Zebra)。
  • 服务端代理:MyCat, ShardingSphere-Proxy, Atlas。