Skip to content

容量规划

容量规划是保证数据库稳定运行的前提,提前规划可以避免突发流量导致的服务不可用。容量规划包括存储规划、性能规划、扩容预案,需要结合业务增长和技术选型综合考虑。

存储估算

数据量计算

存储估算首先需要计算单行数据的大小,包括字段大小、行开销、索引大小。字段大小根据数据类型计算,例如 BIGINT 占用 8 字节,VARCHAR(100) 最多占用 300 字节(UTF8MB4)。行开销包括行头、事务 ID、回滚指针,大约 40 字节。

假设用户表有 10 个字段,包括 BIGINT 主键、VARCHAR 字段、DATETIME 字段,单行大小约 500 字节。1000 万用户的数据量是 500 字节 × 1000 万 = 5GB。加上索引和碎片,实际占用约 10GB。

python
# 存储估算示例
def estimate_storage(num_rows, row_size_bytes, index_overhead=1.5):
    """估算存储空间"""
    data_size = num_rows * row_size_bytes
    total_size = data_size * index_overhead
    return total_size

# 用户表:1000万行,每行500字节,索引开销50%
user_storage = estimate_storage(10_000_000, 500, 1.5)
print(f"用户表存储: {user_storage / 1024 / 1024 / 1024:.2f} GB")
# 输出: 用户表存储: 6.98 GB

增长率估算

存储估算需要考虑数据增长率。历史数据保留周期、业务增长速度、用户活跃度都影响增长。例如日志数据每天新增 1 亿条,每条 200 字节,每天新增 20GB。保留 30 天需要 600GB 存储,保留 90 天需要 1.8TB 存储。

增长率通常不是线性的,需要考虑业务季节性、营销活动、产品功能。例如电商在大促期间的数据量可能是平时的 3-5 倍,社交产品在用户快速增长期的数据量呈指数增长。

存储估算应该预留 50% 的安全空间,应对突发增长和索引膨胀。磁盘使用率超过 80% 时应该触发告警,开始扩容准备。

备份存储

备份存储是容量规划的重要组成部分。全量备份占用空间与数据量相当,增量备份占用空间取决于数据变更量。保留 7 天全量备份和 30 天增量备份,需要额外 2-3 倍数据量的存储。

binlog 和 WAL 日志也需要规划存储,日志保留周期决定了占用空间。例如每天 binlog 增长 10GB,保留 7 天需要 70GB 存储。如果需要时间点恢复,binlog 保留周期应该与备份保留周期一致。

QPS 评估

业务量计算

QPS 评估需要分析业务特点和用户行为。读多写少的业务如内容平台,读写比可能达到 10:1 甚至更高。写多读少的业务如监控日志,读写比可能达到 1:10。电商、社交等业务读写比较平衡,约 1:1 到 1:2。

假设日活用户 100 万,平均每用户每天 50 次请求,其中 30 次读、20 次写。每天总请求量是 5000 万,QPS 是 5000 万 / 86400 ≈ 578。考虑到请求分布不均,峰值 QPS 通常是平均 QPS 的 2-3 倍,峰值 QPS 约 1500。

python
# QPS 估算示例
def estimate_qps(dau, requests_per_user, read_write_ratio=0.6, peak_ratio=3):
    """估算 QPS"""
    total_requests = dau * requests_per_user
    avg_qps = total_requests / 86400
    read_qps = avg_qps * read_write_ratio
    write_qps = avg_qps * (1 - read_write_ratio)
    peak_qps = avg_qps * peak_ratio
    return {
        'avg_qps': avg_qps,
        'read_qps': read_qps,
        'write_qps': write_qps,
        'peak_qps': peak_qps
    }

# 日活100万,每用户50请求,读写比60:40,峰值3倍
qps = estimate_qps(1_000_000, 50, 0.6, 3)
print(f"平均QPS: {qps['avg_qps']:.0f}")
print(f"读QPS: {qps['read_qps']:.0f}")
print(f"写QPS: {qps['write_qps']:.0f}")
print(f"峰值QPS: {qps['peak_qps']:.0f}")

并发连接数

并发连接数影响数据库的内存和 CPU 使用。每个连接占用内存包括线程栈、网络缓冲区、临时表。MySQL 的默认连接数限制是 151,可以通过 max_connections 调整。建议 max_connections 设置为 (可用内存 - Global Buffer) / 每个线程的私有内存。

应用层的连接池大小也需要规划。连接池过小会导致请求等待,连接池过大会导致数据库连接数过多。经验公式是 connections = cores × 2 + effective_spindle_count,对于 SSD 数据库可以简化为 cores × 2。

单机性能评估

单机数据库的性能取决于硬件配置和 SQL 复杂度。简单的点查询单机可以支持 5 万-10 万 QPS,复杂的 JOIN 查询单机只能支持几千 QPS。评估单机性能需要基于实际的 SQL 和数据进行压测。

压测使用工具如 sysbench、JMeter、locust,模拟实际的查询和数据分布。压测指标包括 QPS、响应时间、CPU 使用率、内存使用率、磁盘 I/O。目标是找到单机的性能极限和瓶颈,为扩容提供依据。

扩容预案

垂直扩容

垂直扩容是升级硬件,包括增加 CPU、内存、磁盘。垂直扩容的优势是简单,不需要修改应用和数据。劣势是有上限,硬件性能无法线性提升,成本随性能增加指数增长。

垂直扩容的触发条件包括:CPU 持续超过 80%、内存使用率超过 90%、磁盘 I/O 持续满载、连接数接近上限。扩容前需要评估硬件兼容性,例如主板支持的 CPU 型号、内存插槽数量、磁盘接口类型。

垂直扩容的步骤是备份、停机、更换硬件、恢复、验证。停机时间取决于数据量,对于 1TB 数据,恢复可能需要数小时。可以考虑使用主从切换减少停机时间,先升级备库,然后切换主库。

水平扩容

水平扩容是增加数据库实例,包括读写分离、数据分片。读写分离是将读操作分散到多个只读副本,写操作仍然由主库处理。数据分片是将数据分散到多个主库,每个主库处理部分数据的读写。

读写分离的实现方式包括 MySQL 主从复制、PostgreSQL 流复制、应用层路由。读写分离的挑战是数据延迟,备库的数据可能滞后于主库,应用需要容忍或检测延迟。读写比例达到 5:1 以上时,读写分离收益明显。

数据分片的实现方式包括分库分表、分布式数据库。分库分表是应用层路由,需要修改数据访问层。分布式数据库是自动分片,对应用透明。分片键的选择至关重要,需要考虑数据均匀、查询效率、迁移成本。

扩容时机

扩容应该在资源使用率达到阈值时触发,而不是等到故障发生。建议的阈值是:CPU 使用率持续 70%、内存使用率持续 80%、磁盘使用率超过 80%、连接数接近上限的 80%。提前扩容可以避免突发流量导致的服务不可用。

扩容需要提前规划,包括采购硬件、数据迁移、应用改造、灰度验证。硬件采购周期可能数周,数据迁移可能需要数天,应用改造需要开发和测试。建议提前 3-6 个月开始规划,预留充足的时间应对意外情况。

成本优化

存储成本优化

存储成本优化包括数据归档、冷热分离、压缩算法。数据归档将历史数据迁移到低成本存储,例如从 SSD 迁移到 HDD,从数据库迁移到对象存储。冷热分离是新数据存储在高性能存储,旧数据存储在低成本存储。

压缩算法可以减少存储空间,MySQL 支持 InnoDB 表压缩,PostgreSQL 支持 TOAST 压缩。压缩可以节省 50%-70% 的存储空间,但会消耗 CPU 资源。对于 CPU 充裕、存储紧张的场景,压缩是有效的优化手段。

计算成本优化

计算成本优化包括读写分离、缓存加速、查询优化。读写分离将读操作分散到只读副本,减少主库的计算压力。缓存加速将热点数据缓存到 Redis,减少数据库的查询压力。查询优化通过索引优化、SQL 优化,减少单次查询的资源消耗。

计算成本优化还包括实例选型,选择合适的实例规格。过大的实例浪费资源,过小的实例性能不足。云数据库提供多种实例规格,可以根据实际需求选择,也可以使用弹性伸缩自动调整实例规格。

成本监控

成本监控需要建立成本模型,跟踪不同业务、不同服务的资源使用和成本。云服务的账单详细到每个实例、每个存储类型,可以分析成本构成。自建数据库需要监控硬件采购、电力、机柜、运维的人力成本。

成本优化是一个持续的过程,需要定期审查资源使用情况,识别浪费和优化机会。成本优化的同时不能影响服务的稳定性和性能,需要平衡成本与质量。

容量规划是数据库架构的基础工作,需要结合业务发展、技术选型、成本预算综合决策。准确的容量规划可以避免资源浪费和服务中断,支撑业务的持续增长。