如何实现分库分表
上一篇主要解决的是“查询性能”问题,比如:
- 索引优化
- SQL 优化
- 缓存优化
但随着业务继续增长,系统会进入另一个阶段:
数据库写入量开始成为瓶颈。
典型场景包括:
- 订单量暴涨
- 用户量持续增长
- 日志/消息海量写入
- 高频交易系统
此时,即使查询已经优化得很好,数据库仍然可能被写请求压垮。
因为:
单机数据库的写能力是有上限的。
一、数据库为什么会出现写入瓶颈
MySQL 本质上仍然是:
单机系统。
它最终会受到:
- CPU
- 内存
- 磁盘 IO
- 网络带宽
等物理资源限制。
尤其写操作比读操作更昂贵,因为写入涉及:
- redo log
- binlog
- 磁盘刷盘
- 锁竞争
- 索引维护
因此:
随着写入量增加,数据库很容易出现:
- TPS 上不去
- 锁等待严重
- IO 打满
- 延迟升高
二、为什么主从复制解决不了写瓶颈
很多人想到:
“既然数据库压力大,那加从库不就行了?”
但主从复制只能解决:
“读压力”。
因为:
- 主库负责写
- 从库负责读
所以:
读请求:可以横向扩展
写请求:仍然集中在主库最终:
主库仍然会成为整个系统瓶颈。
因此:
当写入量成为核心问题时,必须拆库。
三、什么是分库分表
分库分表的本质其实非常简单:
“把一份大数据拆散”。
原来:
一个库
一张表现在变成:
多个库
多张表这样可以:
- 分散写入压力
- 分散磁盘 IO
- 分散锁竞争
- 提高整体吞吐量
本质上:
用“多台机器”共同承担写入压力。
四、分表与分库的区别
1. 分表
即:
一张大表拆成多张小表。
例如:
原表:
order拆成:
order_1
order_2
order_3但这些表仍然在:
同一个数据库实例里。
分表主要解决:
(1)单表数据量过大
数据太大后:
- 索引膨胀
- 查询变慢
- B+树层级增加
(2)热点写入问题
写压力可以分散到不同表。
但:
分表不能突破单机数据库性能极限。
因为:
- IO 还是同一台机器
- CPU 还是同一台机器
五、什么是分库
分库:
数据分散到不同数据库实例。
例如:
db_order_1
db_order_2
db_order_3不同库:
- 不同机器
- 不同磁盘
- 不同 CPU
因此:
真正实现了:
写能力横向扩展。
六、垂直拆分与水平拆分
1. 垂直拆分(按业务拆)
例如:
原系统:
user
order
product都在一个库里。
现在拆成:
用户库
订单库
商品库垂直拆分的核心思想:
“按业务边界拆”。
垂直拆分解决的问题:
(1)业务耦合
不同业务隔离。
(2)单库过大
降低复杂度。
(3)团队协作
不同团队维护不同数据库。
但:
垂直拆分并没有真正解决“单表数据量”问题。
例如:
订单表依然可能上亿。
七、水平拆分(真正解决高并发)
水平拆分:
“同一张表的数据拆散”。
例如:
订单表:
order_1
order_2
order_3
order_4每张表只保存部分数据。
八、数据如何拆分
分片规则(Sharding Key)。
这是分库分表最核心的问题。
1. 按范围拆分
例如:
1~1000万 → 表1
1000万~2000万 → 表2优点:
- 范围查询方便
缺点:
- 热点集中
例如: 最新订单永远写最后一个表。
容易形成热点。
2. Hash 拆分(最常见)
例如:
user_id % 4决定写入哪张表。
优点:
- 数据均匀
- 写入均匀
- 压力平衡
缺点:
- 范围查询困难
九、为什么分库分表后性能会提升
因为原来:
所有写请求 → 一个库现在:
写请求 → 多个库分担例如:
4 个库:
理论上:
- 写入能力提升 4 倍
- IO 分散
- 锁竞争减少
本质是:
把单机瓶颈变成集群能力。
十、分库分表带来的核心问题
分库分表不是银弹。
它解决扩展问题, 但会带来大量分布式复杂性。
十一、分布式 ID 问题
原来:
数据库自增主键即可。
分库后:
多个库都会生成:
1
2
3会冲突。
因此必须引入:
全局唯一 ID。
常见方案:
- UUID
- Snowflake
- 号段模式
十二、跨库查询问题
例如:
SELECT * FROM order WHERE create_time > xxx数据散落多个库后:
必须:
- 查询多个库
- 合并结果
复杂度和性能成本急剧上升。
十三、分页问题
例如:
LIMIT 0,20原来:
一个库即可完成。
现在:
多个库:
- 分别查询
- 排序
- 聚合
- 再分页
实现非常复杂。
十四、排序与聚合问题
例如:
ORDER BY
GROUP BY
COUNT
SUM都变复杂。
因为:
数据已经不在同一个节点。
必须:
- 分库计算
- 再汇总
十五、分布式事务问题
这是最核心的问题之一。
原来:
一个数据库事务即可。
分库后:
多个数据库无法直接使用本地事务。
因此:
必须接受:
“最终一致性”。
常见方案:
- 消息队列
- TCC
- Saga
- 补偿机制
十六、为什么互联网系统普遍接受最终一致性
高并发系统优先保证性能和可扩展性。
因此:
互联网系统通常:
放弃强一致性, 换取:
- 高吞吐
- 高可用
- 高扩展
例如:
- 订单先成功
- 库存异步扣减
十七、分库分表的核心原则
1. 不要过早分库分表
因为: 复杂度会暴涨。
优先:
- 索引优化
- SQL 优化
- 缓存
- 主从复制
2. 优先垂直拆分
因为: 业务边界更自然。
3. 分片键最重要
它决定:
- 数据是否均匀
- 是否容易扩展
- 查询性能如何
4. 尽量避免跨库操作
因为: 性能和复杂度都会大幅上升。
十八、分库分表的本质
分库分表本质上是通过“数据拆分”来突破单机数据库写入能力上限。
它的核心收益是:
- 分散写流量
- 分散 IO
- 分散锁竞争
但代价是:
系统从“单机数据库问题”变成“分布式系统问题”。
复杂度会显著提高。
十九、一句话总结
分库分表是高并发系统突破单机数据库写入瓶颈的核心方案,其中垂直拆分解决业务复杂度问题,水平拆分解决数据量和写入压力问题,而真正困难的部分并不是“拆”,而是拆完之后如何处理分布式事务、跨库查询和数据一致性等复杂问题。