容量规划与压测
问题
如何为数据库做容量规划?如何通过压测验证容量是否满足业务需求?
答案
一、容量规划全流程
二、数据量评估
当前数据量 + 未来增量 = 总容量需求
示例:订单表
- 当前:5000 万行,约 20GB
- 月增长:200 万行
- 预留 1 年:5000 万 + 200万 × 12 = 7400 万行
- 加上索引≈ 1.5 倍:20GB × 1.5 × (7400/5000) ≈ 45GB
Buffer Pool 建议 > 热数据大小(最近 3 个月数据)
三、QPS / TPS 评估
| 指标 | 计算方式 | 参考值 |
|---|---|---|
| 日均 QPS | 日请求量 ÷ 86400 | 基础负载 |
| 峰值 QPS | 日均 × 3~5 倍 | 高峰时段 |
| 极端 QPS | 峰值 × 2~3 倍 | 活动/秒杀 |
| TPS | 写请求 QPS | 通常远小于读 QPS |
示例:电商订单系统
- DAU 10 万,人均下单 2 次 → 20 万次写/天
- 写 TPS 平均:200,000 / 86400 ≈ 2.3 TPS
- 写 TPS 峰值:2.3 × 5 ≈ 12 TPS
- 读 QPS(查看订单):写的 10 倍 ≈ 120 QPS
单台 MySQL(8C 16G)通常可承载:
- 简单查询:5000~10000 QPS
- 复杂查询:500~2000 QPS
- 写入:1000~5000 TPS
四、硬件配置建议
| 场景 | CPU | 内存 | 磁盘 | 连接数 |
|---|---|---|---|---|
| 小型(< 1000 QPS) | 4C | 8G | SSD 100G | 100 |
| 中型(1000~5000 QPS) | 8C | 32G | SSD 500G | 300 |
| 大型(5000~20000 QPS) | 16C | 64G | SSD 1T | 500 |
| 超大型(> 20000 QPS) | 32C+ | 128G+ | NVMe | 1000+ |
内存是关键
MySQL 性能主要取决于 Buffer Pool 是否能装下热数据。 如果热数据全在内存 → 读操作几乎不走磁盘 → 性能极高。 Buffer Pool 建议设为物理内存的 60%~80%。
五、压测方案
工具选择
| 工具 | 特点 | 适用场景 |
|---|---|---|
| sysbench | MySQL 专用,内置场景 | 基准压测 |
| mysqlslap | MySQL 自带 | 简单测试 |
| JMeter | 通用,支持 JDBC | 复杂业务场景 |
| wrk / k6 | HTTP 压测 | 通过 API 间接测 DB |
sysbench 压测示例
# 1. 准备数据(10 张表,每张 100 万行)
sysbench oltp_read_write \
--mysql-host=127.0.0.1 \
--mysql-user=root \
--mysql-password=pass \
--mysql-db=sbtest \
--tables=10 \
--table-size=1000000 \
prepare
# 2. 执行压测(64 并发,持续 60 秒)
sysbench oltp_read_write \
--mysql-host=127.0.0.1 \
--mysql-user=root \
--mysql-password=pass \
--mysql-db=sbtest \
--tables=10 \
--table-size=1000000 \
--threads=64 \
--time=60 \
--report-interval=10 \
run
# 3. 清理
sysbench oltp_read_write cleanup
关注指标:
| 指标 | 说明 | 目标 |
|---|---|---|
| TPS | 每秒事务数 | > 预期峰值 QPS |
| Latency P95/P99 | 响应时间 | P99 < 50ms |
| Errors | 错误率 | 0 |
| CPU 使用率 | 服务器 CPU | < 70% |
| IO 使用率 | 磁盘 IO | iowait < 20% |
六、扩容策略
| 方案 | 适用场景 | 复杂度 |
|---|---|---|
| 纵向扩容 | 升级配置(CPU/内存/SSD) | 低 |
| 读写分离 | 读多写少 | 中 |
| 分库分表 | 单库性能瓶颈 | 高 |
| 缓存层 | 热点读 | 中 |
| 归档冷数据 | 数据量过大 | 中 |
扩容时间节点:
建议提前扩容的信号:
1. CPU 持续 > 60%
2. 磁盘空间 < 30%
3. Buffer Pool 命中率 < 95%
4. 连接数 > max_connections × 70%
5. QPS 接近压测极限的 70%
常见面试问题
Q1: 如何估算一个新项目的数据库配置?
答案:
- 用户量 → QPS:DAU × 人均操作数 ÷ 86400 × 峰值系数
- 数据量 → 存储:单行大小 × 总行数 × 1.5(索引开销)
- 内存:确保 Buffer Pool > 热数据量
- 保守原则:初始配置留 2~3 倍余量,便于应对突发
- 压测验证:上线前必须在接近真实环境中压测
Q2: 压测时需要注意什么?
答案:
| 注意点 | 原因 |
|---|---|
| 使用生产级数据量 | 数据量影响索引效率和 IO |
| 模拟真实读写比 | 纯读和纯写测不出真实性能 |
| 渐进加压 | 逐步增大并发,找到拐点 |
| 监控全链路 | DB + 应用 + 网络 + 磁盘 |
| 不在生产库压测 | 影响线上业务 |
Q3: 什么时候该分库分表?
答案:
先做其他优化,分库分表是最后手段:
优化顺序:
1. SQL 优化 + 索引优化(成本最低)
2. 增加缓存层(Redis)
3. 读写分离
4. 升级硬件(纵向扩容)
5. 数据归档(减少数据量)
6. 分库分表(复杂度最高,最后考虑)