设想你在市中心租下一间铺面准备开一家奶茶店。开业前最重要的事,不是买最贵的萃茶机,也不是设计招牌,而是站在门口数客流:早上几点开始排队?午休时段的单量是平日的几倍?周末会不会涌进双倍的人?把这些数字摸清,你才知道该备多少桶珍珠、装多大的冰柜、请几个店员。负载估算,就是系统设计世界里的“数客流”:在写一行代码之前,先量化系统要承受多大的流量、存多少数据、跑多宽的带宽。本文借开奶茶店的完整经历,把面试中最常见的负载估算题,从“心里没底”变成“张口就来”。
负载估算是系统设计面试的“入场券”:它帮你在几分钟内把模糊需求转化为可决策的量化指标,让面试官看到你的工程判断力,而非背诵能力。
目录
可视化演示
动态演示负载估算系统设计的核心机制,通过采集/分析/决策/反馈四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
负载估算系统设计:负载估算 负载估算的基本概念与面试意义 QPS估算方法与峰值系数 核心机制可视化 负载估算系统设计整体架构与关键组件
预估准备:先问清“客流构成”
假如要开奶茶店,第一件事不是急着买机器,而是蹲在门口数三样东西:每天路过多少人?其中进店的占几成?一人平均买几杯?如果店开在写字楼楼下,全部压力挤在午休十二点;开在商场,周末才是大考。需求不同,后厨的规模天差地别。这个道理放到系统设计面试中,就是“先澄清需求再动笔”——面试官抛出“设计一个日活五百万的社交应用”,你不该立刻画架构图,而应先问清输入条件。
这些输入条件中,最重要的有四个。第一个是 DAU(日活跃用户数),即每天真实使用产品的用户量,它是一切流量计算的源头。第二个是 RPU(每用户日均请求数),一位用户一天会发起多少次请求——刷朋友圈、点赞、发消息,每次操作都是一次请求。第三个是读写比例:系统是读多写少(比如视频网站)还是写多读少(比如支付日志),这直接决定后面的硬件与架构倾斜方向。第四个是数据体量:单条记录多大、留存多久、要不要多副本。四个条件好比开店前确认“客单价、出杯数、堂食还是外带比例、食材保质期”,缺一个,后面的估算都是凭感觉。
在面试中,主动澄清需求是一个显著的加分动作。它把一道开放式设计题收敛成一道有边界的算术题,也让面试官看到你不是在背模板,而是真的在“经营这家店”。通常面试官给完 DAU 后会反问“你觉得还需要什么信息”,此时把上面四个指标一口气列出来,就已经赢了一半。
流量估算:从日活到每秒请求
客流数据拿到了:一天一千人进店,人均两杯。要算后厨的出杯速度,得把“一天的量”化成“每秒的量”:一千人乘两杯等于两千杯,除以营业的秒数,平均每秒不到零点三杯。听起来轻松,但下午茶高峰一小时能冲上三百杯,是平均值的几十倍。系统设计里的 QPS(每秒请求数)就是“每秒要出多少杯”,它决定服务器的吞吐底线。
核心公式只有一个,它把“用户规模”翻译成“每秒压力”:
算出平均值只是第一步。现实中的流量从来不是均匀的,早上通勤、午休、晚高峰各有尖峰。业界经验是给平均值乘一个 3~5 倍的峰值系数:五百万 DAU、人均十次请求,平均 QPS 约 579,峰值就要按 1700~2900 来设计。另外,读写要分开算:假设读占九成,读 QPS 约 2600,写 QPS 约 290,两者对应的机器配置完全不同。奶茶店备料从来不是按日均摊,而是按“下午三点这一小时”来备——容量跟着峰值走,这就是流量估算教会我们的第一课。
- 明确日活 DAUDAU 是每天真实打开产品的用户数,它是所有流量计算的起点,必须先和面试官确认,不能自己拍脑袋。
- 乘以人均请求数 RPU每位用户平均每天发起的请求次数,这一步把“用户数”放大成“请求总数”,是新手最容易漏掉的放大系数。
- 除以一天的秒数把日请求总量均匀摊到每一秒,得到平均每秒需要处理的请求量,单位是 QPS。
存储估算:仓库要备多大
奶茶店的仓库要多大,取决于三件事:每天进多少货、食材能放几天、要不要留备份。系统里也一模一样:用户每发一条动态、每传一张图片,都是“进货”。如果一天进两吨珍珠但仓库只能放一吨,隔天就得租新仓库——对应到系统,就是磁盘不够用,服务直接崩溃。所以存储估算的目标,是在上线前回答“我的仓库要租多大”。
来算一笔实际的账:五百万 DAU,每用户每天新增二十条小数据记录,单条 2 KB,日新增约 200 GB;留存一年且做三副本,总容量约 220 TB。这个数字一眼就能看出该上分布式存储还是单机扛得住。仓库面积的答案,决定了你要租“小店”还是“物流中心”。
- 估算单条记录大小一条动态、一笔订单或一张图片在磁盘中占用多少字节,可通过抽样样例或行业经验估算,比如一条纯文本动态约 1~2 KB。
- 计算日新增条数每天新增多少条数据,等于 DAU 乘以每用户每天的写入条数,例如五百万用户每人发两条动态,日新增一千万条。
- 乘以留存天数数据要保留多久?只留 30 天和永久归档,总量相差一个数量级以上,这是存储成本的分水岭。
- 乘以副本系数为防机器故障丢数据,通常存多份,三副本就是在前面结果上乘 3,这也是分布式系统的常见冗余成本。
缓存规划:爆款先备好
奶茶店的爆款珍珠奶茶点单率高达六成,如果每单都现场煮珍珠,客人要等五分钟,队伍能排到街角。精明的店主会提前把珍珠煮好、分装进冰柜,客人点单直接盛——这就是缓存。在系统里,Redis 之类的缓存就是那台冰柜:把高频访问的热点数据提前放进内存,让绝大多数请求在内存里直接返回,而不是每次都去磁盘数据库里翻。
缓存效果的好坏,用一个指标衡量——命中率:
缓存容量怎么估?不需要把所有数据都塞进冰柜,只要装“最热的那批货”:拿全量数据的 10%~20% 估算热点条目数,再乘以单条大小即可。比如全量一亿条、热点两千万条、单条 1 KB,Redis 准备约 20 GB 内存就够了。冰柜满了怎么办?用 LRU(最近最少使用)策略,把最久没卖掉的食材先扔出去。记住:冰柜是给爆款备的,不是给全部库存备的——缓存也是为热点流量而生,别指望它能装下整个世界。
- 统计命中请求数在缓存中直接找到结果、无需访问数据库的请求数量,这是缓存价值的直接体现。
- 除以总请求数用命中数量除以全部请求数量,得到命中比例,例如 90 次命中除以 100 次请求等于 0.9。
- 换算为百分比乘以 100% 得到业界通用的命中率表示,90% 以上说明缓存设计良好,低于 70% 则需要调整缓存策略。
带宽估算:外卖通道有多宽
堂食做出来了,还得送得出去。外卖通道太窄,高峰期全堵在门口:一条水管每秒只能过这么多水,带宽就是系统对外传输数据的通道容量。很多新手只关注 QPS 和存储,却忘了算带宽,结果上线当天发现出口带宽被打满,用户图片加载不出来——相当于奶茶做得飞快,但外卖箱一次只能装三杯。带宽就是那条外卖通道,宽度由“每秒送多少杯、每杯多重”决定:
实际计算:峰值 2000 QPS、单次响应 64 KB,带宽约等于 2000 × 65536 × 8 ≈ 1 Gbps。这是相当可观的一笔开支,所以还要学会“省通道”。第一招是压缩:响应体用 gzip 压一压,体积能缩 60% 以上。第二招是 CDN:把图片、CSS 等静态资源放到用户家门口的 CDN 节点,用户就近取货,核心机房的带宽立刻降下来——相当于在各大写字楼楼下各设一个外卖自提柜,高峰期不再全靠店里那一条通道往外挤。算清带宽,才知道外卖体系要不要建分站点。
- 确定峰值 QPS带宽必须按峰值设计而非平均值,因为高峰期的流量才决定通道是否拥堵,用上面估算出的峰值 QPS 代入。
- 乘以单次响应大小每次请求返回多少数据?一个 JSON 响应 64 KB 还是一条大图 5 MB,直接影响通道占用。
- 字节转比特1 字节等于 8 比特,网络带宽的单位是 bps,必须乘 8 才能与运营商套餐对齐。
容量规划:高峰来了接得住
开业前定员工人数,不是按平时客流算,而是按周末晚高峰算:如果按周二下午的两桌客人配人手,周六晚上七点一到,柜台前的人墙能把店员淹没。系统容量规划同理,别按平均 QPS 配机器,要按峰值并留足余量。这个“余量思维”是架构师和初级工程师的分水岭——你算得再准,也得给突发的流量尖峰和故障切换留出缓冲区。
算完容量,紧接着要回答“机器扛不住怎么办”。这时有两个方向:垂直扩展是换更大的机器,相当于把一家店无限扩建成巨无霸——简单但很快遇到天花板;水平扩展是开分店,加机器分摊客流,弹性好、成本线性增长,这也是互联网大厂普遍采用的方式。分店开多了还要注意排队公平:按用户 ID 哈希分片,把不同用户固定分配到不同窗口,避免某家分店挤爆而另一家空转。更进一步,云上的弹性伸缩是“闲时开三家店、大促临时开三十家、活动结束关掉二十七家”,把固定成本变成可变成本。容量规划的终点,是让店永远接得住客流,又不在淡季白养一堆闲人。
- 取平均 QPS系统平稳运行时每秒处理的请求数,例如前面算出的 579,这是容量的基准值。
- 乘以峰值系数用 3~5 倍覆盖日常流量尖峰,把基准值放大到“最忙那几分钟”的规模。
- 再乘冗余系数留 1.5~2 倍缓冲,用于应对突发热点事件和单机故障替换,最终得到采购容量。
权衡取舍:性价比怎么平衡
是不是店员越多越好、冰柜越大越好?显然不是。请二十个店员但平时只有五桌客人,工资照发;冰柜囤一百桶珍珠,卖不掉只能倒掉。系统设计没有“完美方案”,只有“在预算内接住客流”的平衡方案。算完流量、存储、带宽、容量之后,最后一步是回到账本:这一切要花多少钱,值不值?
成本之外,还要看 SLA(服务可用性承诺)。99.9% 的可用性意味着一年最多宕机 8.7 小时,99.99% 则只有 52 分钟——差距看似微小,成本却可能翻倍。面试中谈取舍,关键是给出“量级判断”而不是“精确数字”:说“峰值约三千 QPS、存储约 200 TB、带宽约 1 Gbps”,比报出“2973.5 QPS“更能体现工程直觉。因为估算的本质是给决策提供数量级依据,而不是做财务决算。开店预算表的最后一行,永远是”用最小的钱接住最大的客流”,负载估算的交付物正是这张预算表——它让一切架构选择都有据可依。
- 确定实例数用规划容量除以单实例的处理能力,向上取整得到需要的机器数量,例如峰值 2600 QPS、单机扛 600,需要约 5 台。
- 乘以单实例时价不同规格的云主机价格不同,内存越大、CPU 越强越贵,这一步把“机器数”变成“时薪”。
- 乘以月小时数一个月约 730 小时,相乘得到月度成本,用来对比不同方案的预算差距。
AI 应用场景
大模型推理服务上线前的容量预估
阶段:模型部署与推理优化
解决的问题:新上线的对话式 AI 产品该买多少张 GPU?买少了并发一高就报 503 错误,买多了显卡闲置、成本失控。传统做法是“先买一批试试”,上线后才发现瓶颈,故障与浪费两头挨打。
具体案例:某客服机器人预计 DAU 五万,每用户日均对话二十轮,每轮平均五百 token。用流量估算的思路:总 token 速率 = 五万 × 二十 × 五百 ÷ 86400 ≈ 每秒 5790 token。再根据单卡推理吞吐(如每秒 2000 token)反推出约需 3 张卡,再乘峰值系数与冗余,最终采购 12 张卡,既扛住晚高峰又不多花冤枉钱。
推荐系统特征平台的存储规划
阶段:特征工程与数据管道
解决的问题:推荐模型每天消费数十亿条特征,特征平台要存多久、存几份、扩多大,没人说得清。传统做法是“不够就加磁盘”,导致存储成本逐年失控,且历史特征过期后依然占用空间。
具体案例:某资讯 App 用存储估算公式:单条特征 256 字节、日新增二十亿条、留存三十天、三副本,算出总量约 420 TB。据此确定分层存储方案——热特征放 SSD、冷特征放对象存储、超期自动清理,存储成本下降 40%。
A/B 实验平台的流量划分
阶段:实验管理与迭代
解决的问题:多个算法实验同时运行,每个实验组需要多少流量才能有统计效力?切分太少实验要跑一个月,切分太多挤占核心链路。传统做法靠拍脑袋定比例,实验结论不可靠。
具体案例:某电商 App 核心链路峰值约一万 QPS。用负载估算给每个实验组分配 2% 流量,即 200 QPS,乘以实验时长推算出样本量,确保七天可出显著结论;同时用容量规划保证所有实验组叠加后不超过总容量的七成,核心交易链路不受影响。
Python 演示
class LoadEstimator: """负载估算器:面向系统设计面试的流量与容量估算工具""" def __init__(self, dau, rpu, peak_factor=3.0): self.dau = dau self.rpu = rpu self.peak_factor = peak_factor self.day_seconds = 86400 def avg_qps(self): """平均每秒请求数""" return self.dau * self.rpu / self.day_seconds def peak_qps(self): """峰值每秒请求数""" return self.avg_qps() * self.peak_factor def daily_storage(self, record_bytes, new_records_per_user): """单日新增存储量(字节)""" return self.dau * new_records_per_user * record_bytes def total_storage(self, record_bytes, new_records_per_user, keep_days, replica=1): return self.daily_storage(record_bytes, new_records_per_user) * keep_days * replica def bandwidth_bps(self, avg_response_bytes, qps=None): """峰值带宽(bit/s)""" q = qps if qps else self.peak_qps() return q * avg_response_bytes * 8 def main(): est = LoadEstimator(dau=200_0000, rpu=10, peak_factor=4) print("平均 QPS: {:.0f}".format(est.avg_qps())) print("峰值 QPS: {:.0f}".format(est.peak_qps())) mb = 1024 * 1024 print("日新增存储: {:.1f} GB".format( est.daily_storage(2 * 1024, 30) / (mb * 1024))) print("一年总量3副本: {:.1f} TB".format( est.total_storage(2 * 1024, 30, 365, 3) / (mb * 1024 * 1024))) print("峰值带宽: {:.2f} Mbps".format( est.bandwidth_bps(64 * 1024) / 1000_000)) if __name__ == "__main__": main()
est = LoadEstimator(dau=200_0000, rpu=10, peak_factor=4)创建估算器:200 万日活、人均 10 次请求、峰值系数取 4。self.day_seconds = 86400把一天的秒数固化为常量,公式里不再出现魔法数字。return self.dau * self.rpu / self.day_seconds平均 QPS 公式:日活乘人均请求数再除以一天秒数。return self.avg_qps() * self.peak_factor峰值 QPS:平均值乘以峰值系数,覆盖高锋时段。return self.dau * new_records_per_user * record_bytes日新增存储:三因子连乘,算一天要存多少字节。return self.daily_storage(record_bytes, new_records_per_user) * keep_days * replica总存储量:日新增再乘留存天数和副本数,得到完整容量。return q * avg_response_bytes * 8带宽公式:QPS 乘响应大小再乘 8,把字节换算成比特。print("峰值 QPS: {:.0f}".format(est.peak_qps()))格式化输出结果,跑一遍就能看到全部关键数字。
常见误区
误区拿到“五百万 DAU”就兴奋地在架构图上写“每秒五百万请求”,完全忘了 DAU 是“人数”而不是“请求数”。
正解DAU 是估算的起点而非终点。每个用户一天会发起很多次请求,必须先用 DAU 乘以每人平均请求数得到日请求总量,再除以 86400 秒才是平均 QPS。就像一万个客人进店不等于一万杯奶茶,得先算清楚一人点几杯。
为何常见:DAU 是面试官给的第一个数字,直觉上最像“流量”,且“每秒”的感觉会让人自动把它当成 QPS。
误区算出平均 QPS 是 579,就直接按 579 设计系统容量,觉得“够用了”。
正解现实流量是脉冲式的,高峰期往往是平均值的 3~5 倍。容量必须按峰值设计,否则一到晚高峰系统就崩。奶茶店按日均十杯每小时备料,下午茶高峰照样排到门外——备料必须按最忙的时段来。
为何常见:平均值好算又好看,而且人天然容易忽略“流量会忽高忽低”这一事实,直到线上告警才醒悟。
误区算存储时只算“一天产生多少数据”,再顺手乘个 365 就交差了,结果和真实容量差出好几倍。
正解完整公式是单条大小 × 日新增 × 留存天数 × 副本数。只留 30 天的数据却按 365 天算,成本高估十倍;反过来说,忘记三副本会让容量低估三倍。留存策略和副本数直接决定量级,一步都不能省。
为何常见:“乘以 365”看起来已经覆盖全年视角,让人误以为考虑周全,实则漏掉了数据生命周期和冗余这两大乘数。
误区只算服务器返回给用户的响应流量,忽略了用户上传图片、视频、请求体本身也要占带宽。
正解上行流量(用户传数据进来)同样是带宽成本的大头,而且云厂商的上行流量往往更贵。计算时要同时看入口和出口,还要把压缩率、协议头开销算进去。外卖通道既要出餐,也要回收脏盘子,双向都占路。
为何常见:下行业务直观、用户看得见,而“用户往里传数据”这件事平时感知弱,特别容易在估算清单里漏掉。
误区觉得面试时要给出“精确”答案,于是憋出"2973.5 QPS"这种数字,还为了凑精确值反复心算。
正解负载估算的本质是量级思维:判断是千级还是万级 QPS、是 TB 级还是 PB 级存储,并展示清晰的推导链。给“约三千 QPS、约 200 TB”远比报个假精确值可信。面试官要的是你的数量级感知和推理过程,不是财务报表。
为何常见:学生时代“精确答案拿满分”的惯性太强,让人误以为设计题也有唯一精确解,反而把精力浪费在无意义的精算上。
面试题
Q1. 某应用日活 500 万,平均每用户每天发起 10 次请求,平均 QPS 约为多少?
- A.58 QPS
- B.579 QPS← 正确答案
- C.5790 QPS
- D.50000 QPS
答案:B。平均 QPS = DAU × RPU ÷ 86400 = 500 万 × 10 ÷ 86400 ≈ 579。A 是忘记乘 10 再除以 86400 后少算一位,C 是没除以 86400,D 是把 DAU 直接当 QPS。像奶茶店数客流,先乘人均杯数再分摊到每秒。
Q2. 估算峰值 QPS 时,通常应在平均 QPS 基础上乘以什么系数?
- A.1 倍
- B.3~5 倍← 正确答案
- C.100 倍
- D.10~20 倍
答案:B。业界经验是用 3~5 倍峰值系数覆盖早晚高峰等流量尖峰。1 倍等于没留余量,100 倍则过度设计浪费成本。就像奶茶店备料按下午茶高峰的客流来备,而不是按全天平均客流。
Q3. 估算存储总量时,必须明确哪些输入条件?
- A.单条记录大小← 正确答案
- B.日新增条数← 正确答案
- C.留存时长← 正确答案
- D.CPU 核数
答案:ABC。存储总量 = 单条大小 × 日新增 × 留存天数 × 副本数,前三项缺一不可。CPU 核数影响的是计算能力而非存储容量,属于典型的干扰项。就像算仓库面积要知道每箱货多大、每天进几箱、放几天,而不是问送货司机开什么车。
Q4. 某系统峰值 QPS 为 2000,单次响应 64 KB,峰值带宽约为多少?
- A.32 MB/s
- B.125 MB/s← 正确答案
- C.2 GB/s
- D.64 MB/s
答案:B。带宽 = 峰值 QPS × 响应大小 × 8 = 2000 × 64 KB × 8 ≈ 128,000 KB/s ≈ 125 MB/s(约 1 Gbps)。A 少了 ×8 的字节转换,C 多算了一个数量级,D 只算了单次响应大小。就像外卖通道的宽度由“每秒送几杯、每杯多重”共同决定。
Q5. 缓存命中率达到 90% 意味着什么?
- A.9 成请求直接取缓存← 正确答案
- B.9 成数据永不丢失
- C.系统容量缩小九成
- D.仅 9 成用户能访问
答案:A。命中率指请求在缓存中直接命中的比例,90% 意味着只有 10% 的请求穿透到数据库,数据库压力骤降。B 混淆了缓存与持久化,C 与容量无关,D 则是把命中率错误理解为用户覆盖率。相当于一百杯奶茶有九十杯直接从冰柜盛出。
Q6. 数据存储采用三副本冗余后,存储容量需求如何变化?
- A.保持原容量
- B.扩大为三倍← 正确答案
- C.缩小三分之一
- D.扩大为九倍
答案:B。三副本指每份数据在三个节点各存一份,容量需求是原来的三倍。保持原容量会丢数据冗余,缩小三分之一是方向性错误,九倍则混淆了副本与分片的叠加关系。就像贵重食材放三个仓库各存一份,仓库总面积自然是三倍。
Q7. 下列关于水平扩展的说法,正确的是?
- A.换性能更强的单机
- B.增加机器分摊负载← 正确答案
- C.仅扩大内存容量
- D.与垂直扩展完全相同
答案:B。水平扩展是增加更多机器共同分担流量,垂直扩展才是换更强的单机。A 是垂直扩展的定义,C 只是硬件升级的一种,D 混淆了两种扩展方式。好比奶茶店客流太大时,开分店(水平)比把一家店无限扩建(垂直)更灵活。
Q8. 某应用 DAU 100 万,平均 QPS 约 1157,则每用户每天平均发起多少次请求?
- A.1 次/天
- B.10 次/天
- C.100 次/天← 正确答案
- D.1000 次/天
答案:C。由平均 QPS = DAU × RPU ÷ 86400 反推,RPU = 1157 × 86400 ÷ 100 万 ≈ 100 次/天。本题考的是对公式的逆向运用,A、B 反推结果对不上,D 则会让平均 QPS 变成 10000 以上。就像知道全天总杯数和客人总数,反推人均几杯。
Q9. 系统设计面试中做负载估算的主要价值有哪些?
- A.为容量规划提供依据← 正确答案
- B.帮助识别系统瓶颈← 正确答案
- C.替代全部业务代码
- D.支撑技术方案选型← 正确答案
答案:ABD。负载估算为容量规划、瓶颈分析和技术选型提供量化依据,这是它的三大核心价值。C 完全跑偏,估算是设计准备,不是替代实现。就像开店前数客流是为了定规模、找瓶颈、选设备,而不是代替做奶茶。
Q10. 关于系统高峰期的处理策略,以下哪些是合理的?
- A.提前扩容应对高峰← 正确答案
- B.限流保护后端← 正确答案
- C.CDN 缓存热点← 正确答案
- D.关闭系统日志
答案:ABC。提前扩容是容量规划的落地,限流可在超预期流量下保护核心服务,CDN 缓存热点能分流静态请求,三者都是常规手段。关闭日志属于因噎废食,会破坏可观测性,故障时连排查依据都没有。就像大促前多备货、控制进店人数、设自提柜分流,但绝不能关掉监控摄像头。