分库分表策略

选择合适的分片策略是分库分表的核心,直接影响系统性能和可扩展性。

垂直拆分 ⭐⭐⭐⭐

垂直分库

定义:按业务模块将表分散到不同的数据库。

原来:单库包含所有表
┌──────────────────────────────┐
│        Main Database         │
│  ┌──────┬──────┬──────────┐  │
│  │ User │ Order│ Product  │  │
│  └──────┴──────┴──────────┘  │
└──────────────────────────────┘

垂直分库后:
┌──────────┐  ┌──────────┐  ┌──────────┐
│ User  DB │  │ Order DB │  │Product DB│
│  User    │  │  Order   │  │ Product  │
└──────────┘  └──────────┘  └──────────┘

优点

  • 业务解耦,符合微服务架构

  • 突破单库连接数限制

  • 提升并发能力

缺点

  • 跨库 JOIN 困难

  • 分布式事务问题

垂直分表

定义:将一张宽表拆分为多张表。

优点

  • 冷热数据分离,提升缓存命中率

  • 减少 I/O,提升查询性能

  • 核心字段更易维护

缺点

  • 需要额外 JOIN


水平拆分 ⭐⭐⭐⭐⭐

水平分库

定义:将同一张表的数据分散到多个库。

优点

  • 突破单库连接数和 QPS 限制

  • 提升并发写入能力

缺点

  • 跨库 JOIN 和事务复杂

  • 需要分片路由

水平分表

定义:将同一张表的数据分散到多个表。

优点

  • 突破单表性能瓶颈

  • 减少单表索引深度,提升查询性能

缺点

  • 跨表 JOIN 困难

  • 需要处理分片路由


分片算法 ⭐⭐⭐⭐⭐

1. 取模算法

公式shard_id = user_id % shard_count

优点

  • 简单,数据分布均匀

  • 查询性能好(精确定位分片)

缺点

  • 扩容困难:增加分片需要迁移大量数据

  • 例如:4 个分片扩展到 5 个,80% 数据需要迁移

2. 范围算法

规则:按 ID 范围划分分片。

优点

  • 扩容简单:只需增加新的范围分片

  • 适合范围查询:WHERE user_id BETWEEN 1000 AND 5000

缺点

  • 数据倾斜:新用户集中在最新分片,导致热点

  • 历史分片可能空闲

优化:动态范围调整或混合算法

3. 一致性哈希

原理:使用哈希环,减少扩容时的数据迁移。

优点

  • 扩容时只需迁移 1/N 数据(N 为节点数)

  • 数据分布相对均匀

缺点

  • 实现复杂

  • 需要虚拟节点防止数据倾斜

算法对比

算法
数据分布
扩容难度
适用场景

取模

均匀

困难

分片数固定,不需扩容

范围

可能倾斜

简单

需要范围查询,数据增长可预测

一致性哈希

均匀

较简单

需要频繁扩容


分片键选择 ⭐⭐⭐⭐⭐

选择原则

  1. 数据均匀分布:避免热点

  2. 查询条件包含分片键:精确路由,避免广播

  3. 业务相关性强:如用户 ID、订单 ID

  4. 避免跨分片:相关数据在同一分片

常见分片键

场景
推荐分片键
理由

用户表

user_id

用户维度查询占大多数

订单表

user_id

按用户查询订单最常见

商品表

shop_id

按店铺查询商品

日志表

时间 + user_id

范围查询 + 用户维度

错误案例

错误1:选择非查询条件的字段

错误2:选择分布不均的字段


跨分片查询 ⭐⭐⭐⭐⭐

问题

分库分表后,跨分片的 JOIN、聚合、排序都变得复杂。

场景1:跨分片 JOIN

场景2:全局排序

解决方案

方案1:冗余数据(推荐)

方案2:应用层 JOIN

方案3:全局表

方案4:ES 聚合


扩容策略 ⭐⭐⭐⭐

扩容挑战

取模算法扩容

结论:约 50% 数据需要迁移

解决方案

方案1:翻倍扩容

方案2:逻辑分片 + 物理分片

方案3:在线迁移工具


面试要点 ⭐⭐⭐⭐⭐

Q1: 垂直分库和水平分库的区别?

  • 垂直:按业务拆分,解决业务耦合问题

  • 水平:按数据量拆分,解决性能和存储问题

Q2: 常见的分片算法有哪些?

  • 取模:均匀分布,但扩容困难

  • 范围:扩容简单,但可能数据倾斜

  • 一致性哈希:扩容时迁移数据少

Q3: 如何选择分片键?

  • 数据均匀分布

  • 查询条件包含分片键

  • 避免跨分片查询

Q4: 分库分表后如何处理 JOIN?

  • 数据冗余(推荐)

  • 应用层 JOIN

  • 全局表

  • 使用 ES 等搜索引擎

Q5: 取模算法扩容为什么困难?

  • 分片数变化后,大部分数据的分片位置都会变

  • 例如 4 → 5,80% 数据需要迁移

Q6: 如何减少扩容时的数据迁移?

  • 翻倍扩容

  • 逻辑分片 + 物理分片

  • 一致性哈希

Q7: 分库分表后如何生成全局唯一 ID?

  • 雪花算法(推荐)

  • 数据库号段

  • Redis INCR

  • UUID(无序,不推荐)


参考资料

  1. 书籍推荐:《大型网站技术架构》、《亿级流量网站架构核心技术》

Last updated