1. 为什么要分库分表?
1.1 单库瓶颈表现
- 存储瓶颈:单表数据超过5000万行,查询性能急剧下降
- 性能瓶颈:单库QPS超过5000后响应延迟显著增加
- 可用性风险:单点故障导致全系统不可用
1.2 突破性优势
text
+----------------+--------------+-----------------+
| 指标 | 单库单表 | 分库分表(16分片) |
+----------------+--------------+-----------------+
| 写入吞吐量 | 2000 TPS | 32000 TPS |
| 查询延迟 | 120ms | 15ms |
| 数据容量 | 500GB | 8TB |
+----------------+--------------+-----------------+
2. 分片策略深度解析
2.1 水平分片 vs 垂直分片
分片类型 水平分片 垂直分片 按行拆分 按时间范围拆分 按列拆分 按业务模块拆分
2.2 典型分片算法对比
算法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
哈希取模 | 均匀分布场景 | 数据分布均匀 | 扩容困难 |
一致性哈希 | 需要动态扩容 | 扩容影响小 | 实现复杂 |
范围分片 | 时序数据 | 支持范围查询 | 容易产生热点 |
基因分片 | 关联查询优化 | 支持跨表关联 | 设计复杂 |
3. 生产环境实施流程
3.1 分片方案设计
java
// 基因分片算法示例
public class GeneSharding {
public static String getShard(String orderId) {
// 提取用户ID后四位作为基因
String gene = orderId.substring(orderId.length()-4);
int hash = Math.abs(gene.hashCode()) % 16;
return "shard_" + hash;
}
}
3.2 数据迁移方案
text
1. 全量迁移:使用DataX工具导出历史数据
2. 增量同步:通过Canal监听binlog
3. 数据校验:对比MD5校验和
4. 流量切换:灰度切换读/写流量
3.3 应用改造要点
xml
<!-- MyBatis分表配置示例 -->
<insert id="insertOrder">
<!-- 自动路由到对应分表 -->
INSERT INTO order_${shardIndex}
VALUES (#{orderId}, #{amount})
</insert>
4. 分库分表中间件选型
4.1 主流方案对比
工具 | 接入方式 | 功能完整性 | 学习成本 | 社区支持 |
---|---|---|---|---|
ShardingSphere | JDBC代理 | ★★★★★ | ★★☆ | ★★★★★ |
MyCat | 数据库代理 | ★★★★☆ | ★★★ | ★★★☆ |
Vitess | gRPC接口 | ★★★★☆ | ★★★★ | ★★★★ |
4.2 ShardingSphere配置示例
yaml
application-sharding.yml
spring:
shardingsphere:
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds${0..1}.t_order_${0..7}
database-strategy:
standard:
sharding-column: user_id
sharding-algorithm-name: db_hash
table-strategy:
standard:
sharding-column: order_time
sharding-algorithm-name: table_range
5. 常见问题解决方案
5.1 分布式事务处理
java
// Seata分布式事务示例
@GlobalTransactional
public void createOrder(Order order) {
orderDao.insert(order); // 写订单库
inventoryDao.deduct(order); // 写库存库
accountDao.updateBalance(order); // 写账户库
}
5.2 跨分片查询优化
sql
-- 使用全局索引表
CREATE TABLE global_index (
biz_id VARCHAR(32) PRIMARY KEY,
shard_key VARCHAR(32) NOT NULL
);
-- 查询时先查索引表
SELECT shard_key FROM global_index WHERE biz_id = 'ORDER_123';
SELECT * FROM t_order_${shard_key} WHERE order_id = 'ORDER_123';
6. 监控与调优
6.1 关键监控指标
指标类别 | 监控项 | 报警阈值 |
---|---|---|
资源使用 | 分片存储空间使用率 | >80% |
性能指标 | 跨分片查询比例 | >5% |
业务指标 | 分片数据分布偏差率 | >15% |
6.2 性能调优技巧
text
1. 热点分片处理:动态调整路由策略
2. 查询优化:强制指定分片键
3. 缓存加速:二级缓存+布隆过滤器
4. 连接管理:合理配置连接池参数
7. 真实案例:电商平台改造
7.1 改造前架构
text
[应用集群]
|
[MySQL主从]
500GB数据
3000 TPS
7.2 分库分表方案
text
16个分库(用户ID哈希)
每个库包含:
8个订单表(时间范围分片)
4个支付表(订单ID基因分片)
7.3 改造成效
text
峰值处理能力:52000 TPS → 提升17倍
平均查询延迟:86ms → 9ms
年度存储成本:降低42%
8. 演进路线建议
timeline
阶段1 : 单库读写分离
阶段2 : 垂直分库(业务拆分)
阶段3 : 水平分表(单业务分表)
阶段4 : 多维度分库分表
阶段5 : 单元化架构
技术选型建议:
• 数据量<1TB:使用中间件方案
• 数据量>1TB:考虑NewSQL数据库(TiDB/CockroachDB)
• 超高并发场景:结合内存数据库(Redis/Aerospike)
通过合理的分库分表策略,可以使传统关系型数据库支撑起海量数据场景。关键在于根据业务特征选择合适的分片策略,并建立完善的监控运维体系。