容量估算方法

候选人大周在面试中设计了一个评论系统,方案看起来很完善。面试官问:"你的系统能支撑多少并发用户?需要多少台服务器?"

大周支支吾吾:"呃...应该能撑挺多的吧..."

面试官追问:"能不能给个具体数字?"

大周彻底卡壳。

这是系统设计面试中最常见的翻车场景——方案吹得天花乱坠,一问容量就露馅

【架构权衡】

容量估算是系统设计的基本功。面试官问这个问题,不是想刁难你,而是想看你有没有"工程量化意识"。一个只知道画架构图的候选人,和一个能说出"按日活1000万、峰值QPS 5万、需要32核128G服务器8台"的候选人,是两个完全不同的层次。

一、容量估算的核心公式 🔴

1.1 必备的几个数字

面试前,你必须记住这几个基准数字:

组件单机指标说明
Nginx3-5万 QPS普通静态资源
Redis10-15万 QPS简单GET/SET操作
MySQL单表读3000-5000 QPS有索引的简单查询
MySQL单表写1000-2000 QPS单表INSERT/UPDATE
Kafka10-50万 QPS取决于分区和硬件
RocketMQ5-30万 QPS持久化模式下
Elasticsearch1-3万 QPS复杂查询场景
⚠️

这些数字是保守估算,实际性能取决于机器配置、网络环境、数据复杂度。但面试时用保守数字更安全——你可以说"单机保守估计",这样即使有偏差也有退路。

1.2 核心公式

QPS估算公式

峰值QPS = 日活 × 人均日访问次数 × 峰值因子 / 86400

示例:日活1000万,人均日访问10次,峰值因子5
峰值QPS = 10000000 × 10 × 5 / 86400 ≈ 5787 QPS

并发用户估算

并发用户数 = 峰值QPS × 平均响应时间(秒)

示例:峰值QPS 5000,平均响应时间200ms
并发用户数 = 5000 × 0.2 = 1000 并发用户

机器数量估算

所需机器数 = 峰值QPS / 单机QPS × 冗余系数

示例:峰值QPS 5000,单机处理3000 QPS,冗余系数1.5
机器数 = 5000 / 3000 × 1.5 ≈ 3 台(取整为4台)

存储容量估算

总存储量 = 日活用户数 × 每用户数据量 × 数据保留天数 × 副本系数

示例:日活1000万用户,每用户每天产生100条行为数据,
每条数据1KB,保留30天,2副本
存储量 = 10000000 × 100 × 1KB × 30 / 2 ≈ 150GB / 天

1.3 二八法则与峰值因子

二八法则:80%的流量发生在20%的时间内。

这个法则在互联网产品中屡试不爽:

  • 早高峰(9-11点)和晚高峰(19-22点)占全天流量的60%以上
  • 活动期间峰值可能是平日的5-10倍
  • 热搜事件可能带来100倍的流量突增

峰值因子计算

峰值因子 = 峰值QPS / 平均QPS

互联网产品峰值因子通常在2-10之间:
- 普通产品:2-3
- 社交媒体:5-8
- 秒杀/活动:10-50

【架构权衡】

容量估算不是一次性的事。你需要考虑三个维度:当前容量(按现有日活估算)、半年容量(按增长预期估算)、极端容量(按突发事件估算)。只估算当前的叫初级工程师,能估算三个维度的才是有全局视野的工程师。

二、日活推算峰值QPS 🔴

2.1 典型场景推算

场景1:微博类社交产品

已知:日活1亿,用户平均每天刷30分钟,每分钟刷新3次Feed
日均请求数 = 1亿 × 3次/分钟 × 30分钟 = 90亿次
峰值因子 = 5(日内峰值)
峰值QPS = 90亿 / 86400 × 5 ≈ 52万 QPS

场景2:电商类交易产品

已知:日活5000万,用户平均浏览20个商品详情页,加购3次,下单1次
日均请求数 = 5000万 × (20 + 3 + 1) = 12亿次
峰值因子 = 8(集中在午间和晚间)
峰值QPS = 120亿 / 86400 × 8 ≈ 11万 QPS

场景3:视频类娱乐产品

已知:日活2亿,人均观看30分钟视频,加载视频列表100次
日均请求数 = 2亿 × 100 = 200亿次
峰值因子 = 3(视频播放相对平滑)
峰值QPS = 200亿 / 86400 × 3 ≈ 69万 QPS

2.2 实际面试案例

面试官:设计一个抖音的Feed流系统,日活6亿,估算一下存储容量。

候选人:日活6亿,假设用户平均关注200人,每天产生1条新视频,每个人要看最近20条。

那么每个用户每天的Feed数据量是 200 × 20 = 4000 条,但不需要全部存储,用户每次请求时实时聚合即可。

关键存储是视频本身:假设每个视频100MB,6亿用户每天有10%发视频,那就是6亿 × 10% = 6000万视频/天。

每个视频100MB,每天新增存储约 6000万 × 100MB = 6TB。

保留30天,需要 180TB 存储。考虑三副本,实际需要 540TB。用64TB的机器,需要9台。

面试官:那你的系统QPS能撑多少?

候选人:6亿日活,人均日访问30次,每次加载20条视频。

总请求数 = 6亿 × 30 × 20 = 3600亿次请求/天

平均QPS = 3600亿 / 86400 ≈ 42万

峰值因子保守取5,峰值QPS约210万。

按Nginx单机5万QPS算,需要42台;按Redis缓存命中率80%算,回源QPS约42万,按MySQL单表5000 QPS算,需要84个分表...

面试官:够了,你已经说服我了。

【面试官心理】

当候选人能给出精确到个位的机器数量时,面试官通常会有两种反应:一种是"这人真厉害",另一种是"这人是不是在吹牛"。关键区别在于你能不能说出"保守估计"和"假设条件"。精确的数字 + 合理的假设条件 = 说服力。

三、存储容量精确估算 🟡

3.1 用户数据存储

用户表存储估算:

字段估算:
- user_id: BIGINT, 8字节
- username: VARCHAR(32), 平均16字节
- phone: VARCHAR(20), 20字节
- profile_url: VARCHAR(256), 平均64字节
- 注册时间/更新时间: 16字节
- 其他扩展字段: 64字节

单用户数据 ≈ 200字节
1亿用户 ≈ 200MB(纯数据)

考虑索引(主键索引 + 手机号索引 + 用户名索引):
索引空间 ≈ 数据空间的1.5倍

用户表总存储 ≈ 200MB × 1.5 × 1亿 = 300GB

3.2 日志数据存储

访问日志估算:

字段:时间戳(8B) + user_id(8B) + 请求路径(64B) + IP(16B) + 响应时间(4B) + 其他(64B)
单条日志 ≈ 164字节

日活1亿,人均日访问100次
日日志量 = 1亿 × 100 × 164B = 1640GB ≈ 1.6TB

保留7天 = 11.2TB
保留30天 = 48TB

压缩后:日志通常压缩比1:5~1:10
30天压缩后 ≈ 5-10TB

3.3 消息队列积压容量

Kafka积压估算:

峰值QPS = 10万
每条消息平均大小 = 1KB
峰值持续时间 = 5分钟
积压消息数 = 10万 × 300秒 = 3000万条
积压存储 = 3000万 × 1KB = 30GB

设计积压容量 = 峰值积压 × 3倍安全系数 = 90GB

:::tip 💡

生产环境中,消息队列积压是最容易被忽略的容量黑洞。很多系统上线初期没问题,三个月后开始出现消息延迟,一查才发现上游流量增长了5倍,但没人扩容broker。所以容量规划时,要问清楚增长预期。

:::

四、网络带宽估算 🟡

4.1 出口带宽计算

场景:视频网站,日活1亿,峰值QPS 10万
每个请求平均响应体 = 10KB
峰值带宽 = 10万 × 10KB = 1GB/s = 8Gbps

通常需要:
- 核心机房出口带宽 10Gbps+
- CDN带宽按流量计费
- 考虑Gzip压缩,实际带宽可降低60%

4.2 内网带宽计算

微服务架构中,服务间调用带宽往往比出口带宽更大:

假设有10个微服务,每个请求平均触发5次内部调用
内网带宽 = 峰值QPS × 10 × 5 × 平均调用响应 = 10万 × 50 × 1KB = 5GB/s

内网通常用万兆网卡,但要注意跨机房调用延迟。

五、内存与CPU估算 🟡

5.1 缓存容量估算

Redis缓存估算:

场景:电商商品详情页缓存
- 日活5000万,商品数1000万
- 人均访问商品数:20个/天
- 缓存命中率目标:90%

需要缓存的商品数 = 1000万 × 90% = 900万个
每个商品缓存大小(JSON):约5KB
热点商品(约10%):100万个 × 5KB = 5GB
冷门商品(约90%):800万个 × 5KB = 40GB

Redis总需求 ≈ 50GB
考虑Redis主从 + 哨兵,实际部署 ≈ 100GB

5.2 JVM堆内存估算

Java服务内存估算:

假设单次请求占用堆内存:200KB
并发用户数:1000
同时在内存中的请求:1000 × 200KB = 200MB

加上业务对象、中间缓存:
- 基础开销:512MB
- 应用对象:1GB
- 缓存对象:2GB
- 冗余空间:512MB

JVM堆内存建议:4GB
机器配置建议:8核16G

:::warning ⚠️

很多候选人能估算QPS,但忽略了JVM内存。我见过最典型的翻车:候选人设计方案时很完美,上了生产才发现JVM OOM。原因是没考虑到GC时对象晋升的额外内存需求。JVM堆内存要留20-30%的冗余。

:::

六、面试应答模板 🟢

6.1 万能应答结构

当面试官问"估算一下你的系统容量"时,按这个结构回答:

第一步:假设条件
"假设日活X万,峰值因子取Y,人均日访问Z次..."

第二步:QPS估算
"日均请求 = X万 × Z = M次
 峰值QPS = M × Y / 86400 ≈ Q次/秒"

第三步:存储估算
"每用户数据量约A字节,总用户B亿...
  存储量 = X TB,保留N天 = Y TB"

第四步:机器需求
"按单机QPS N计算,需要X台应用服务器
 按缓存命中率H%计算,需要Y台Redis
 按数据量D计算,需要Z台MySQL分表"

第五步:安全系数
"考虑N倍峰值冗余和M倍增长空间..."

6.2 常见问题应答

Q:日活100万,估算系统需要多少台服务器?

峰值QPS = 100万 × 10次 × 5(峰值因子)/ 86400 ≈ 579 QPS

应用服务器:单机3000 QPS,需要1台(冗余取2台)

Redis缓存:单机10万 QPS,1台足够

MySQL:单机写2000 QPS,读5000 QPS,主从2台

结论:4台服务器足够支撑日活100万。

Q:系统瓶颈在哪?怎么扩容?

主要瓶颈通常是数据库:

  • MySQL单表超过2000万记录后性能下降 → 分表
  • 单机连接数上限约2000 → 连接池 + 分库
  • 热点数据导致缓存穿透 → 多级缓存

扩容顺序:先缓存 → 再读写分离 → 最后分库分表

【架构权衡】

容量规划有一个重要原则:不要过度设计,但也不要裸奔。我的经验是:基础设施按3倍峰值设计,业务代码按5倍峰值预留扩展点。这不是浪费,而是给系统留出喘息空间——互联网产品的流量增长,往往比任何人预测的都快。

七、真实面试回放 🟡

面试官:设计一个外卖配送ETA系统,预计日订单量1000万,估算需要多少计算资源。

候选人(小杨):先说假设:每笔订单需要计算3次ETA(下单、接单、开始配送),每次计算涉及10个商家/骑手节点的路径规划。

计算量 = 1000万 × 3 × 10 = 30亿次路径计算/天

平均QPS = 30亿 / 86400 ≈ 3.5万次/秒

峰值因子取5,峰值QPS ≈ 18万次/秒

单次路径计算(用A*算法)约10ms,单机每秒处理100次

需要机器数 = 18万 / 100 = 1800台计算服务器

面试官:1800台太多了,有没有优化空间?

小杨:有三个优化方向:

一是预计算:骑手常驻区域的路径提前算好缓存,命中率预计60%,计算量降为 18万 × 40% = 7.2万次/秒,需要720台。

二是异步计算:ETA下单时给出预估值,实际接单后异步精计算,峰值可平滑到平均,计算量 = 3.5万次/秒,需要350台。

三是降级策略:高峰期只计算关键路径,非关键路径延迟30秒。

综合来看,350台服务器是合理目标。

面试官:很好。

【面试官手记】

小杨的亮点在于三点:第一,给出假设条件(三种场景、三种优化策略),不是拍脑袋;第二,量化每个优化点的收益(命中率60%、峰值因子5),有数据支撑;第三,面对"太多"的质疑,没有硬扛,而是快速给出优化方案。这种"估算-分析-优化"的闭环思维,正是P6/P7面试官最想看到的。

容量估算是系统设计的基本功,也是最能展示"工程师素养"的环节。记住:假设条件要说清楚,公式要一步步列,计算过程要让面试官跟上。当你用数字说服面试官的时候,这场面试就已经赢了一半。