Skip to content

필사 모드: 系统设计面试准备法 — 被打分的不是答案,而是一步步收敛的45分钟

中文
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

引言 — 为什么45分钟会在白板前蒸发

有一个常见场景。面试官刚说完"请设计一个短链服务",候选人就拿起了笔。客户端、负载均衡、Web服务器、数据库。五个方框六条箭头,三分钟就画完了。然后大约过了25分钟,面试官问:"一天需要处理多少请求?"候选人这才意识到,自己什么都没定,只是画了张图。

这次失败不是知识问题。同一个候选人既懂Kafka也懂分片。崩掉的是推进方式。系统设计面试是故意留成开放式、让标准答案不存在的题目,所以评分表也朝向过程而不是成果物。

坦白说,业内对这种形式在多大程度上能预测真实工作能力也存在怀疑。在白板前的45分钟,和实际工作中的设计活儿相当不同。不过撇开那场争论,对一个下周就要通过面试的人来说,需要的是了解这个形式的规则。这篇文章讲的就是那些规则。

面试官真正在打分的东西

Alex Xu的《System Design Interview》(2020)把这类面试整理成四个阶段:理解问题并划定范围、提出概略设计并取得共识、深入挖掘、收尾。这个结构之所以流传很广,是因为真实的评分表大体上也有相同的几根轴。

在多数公司,面试官要填的反馈项只有四五条。有没有自己把需求收窄,概略结构和需求是否对得上,能不能把某一点挖深,每个选择有没有说出代价,想法有没有讲得让人听得懂。这里通常没有"是否给出了最优架构"这一条。

面试官要找的不是标准答案,而是候选人在有约束时懂得放弃什么。如果预算无限、时间无限,那就不需要设计了。设计就是决定哪些事不做,而解释为什么可以不做,才是这场面试的主体。

年限越高,权重越会移动。招初级时"知道什么"占比更大,招资深时"知不知道自己不知道什么"变得更大。把自己从没运维过的领域说得像运维过一样的候选人,哪怕知识量很大,也很难拿到资深评级。

45分钟怎么用 — 先把时间预算说出口再开始

不提前定好时间分配,45分钟一定会从前半段漏光。下面是一份稳妥的默认值。

  • 需求整理5分钟。用两三条功能需求把范围切出来,再把非功能需求用数字确定下来。
  • 概略设计10分钟。方框和箭头到这里才第一次出现。再加上一两个API和数据模型的骨架。
  • 深入挖掘15分钟。进入面试官表现出兴趣的那一点。这一段实际上占了一半分数。
  • 瓶颈与扩展10分钟。流量涨十倍时哪里先坏,那时候要改什么。
  • 收尾5分钟。还剩下的风险、下一步要测什么、时间再多一点会看什么。

这里有个实战小技巧。别把这份预算只留在自己心里,要出声宣布。"我打算用五分钟左右整理需求,再用十分钟左右画出概略结构,然后按您感兴趣的部分深入展开,可以吗?"这一句话同时做了两件事。它把节奏的主导权拿了过来,也发出了一个信号:你是会和对面的人对齐节拍的人。

然后看表。自我诊断只要记住一条标准就够。如果15分钟过去了还没画出第一个方框,说明你在需求上停留太久;如果5分钟就画完了整张图,说明你什么都没定

值得背下来的数字

设计中来回的大部分判断,都建立在数量级的直觉之上。为什么要加缓存、为什么要分区域、为什么要减少同步调用,全都来自下面这张表里的间隔。

操作大致耗时感觉
L1缓存访问1纳秒上下基本等于免费
主内存访问100纳秒缓存的100倍
NVMe SSD随机读几十微秒内存的几百倍
同一区域内网络往返0.5毫秒上下SSD的十倍左右
机械硬盘寻道10毫秒该避开的区间
首尔与美国西部往返100毫秒以上光速定下的下限

这张表的原型是Jeff Dean整理、Peter Norvig广为传播的"每个程序员都该知道的延迟数字"。引用时多以2012年版为准,其中一部分绝对值已经过时了。尤其是存储那一侧,这些年快了一个数量级不止。即便如此,层与层之间的间隔依然有效,面试里需要的也不是精确值,而是这个间隔

只有最后一行,无论硬件怎么变都不会缩短。光在光纤中大约以每秒20万公里前进。首尔到美国西海岸单程约9000公里,所以光是物理下限就已经是往返90毫秒。再加上真实路由的绕行,实测通常落在130毫秒上下。知道这个数字,"我会加CDN和边缘缓存"就不再是流行词的堆砌,而是计算的结论。

可用性的数字也值得背一个。99.9%大约是一年停机8.8小时,99.99%大约是53分钟。面试官问"可用性目标是多少"时,你如果能当场做出这个换算,后面的对话就会自然滑向多可用区和故障切换的成本。

估算练习 — 从一个DAU推到QPS和存储

粗略估算靠的不是天赋,而是重复。起点是两次取整。一天是86,400秒,但我们把它凑成10万秒,一年凑成3000万秒。这样计算就进入了心算范围。一天一百万请求约等于10 QPS(准确说是11.6),一天一亿请求约等于1000 QPS。

我们来实际跑一遍。假设日活用户1000万,一个人一天发20次请求,那就是一天2亿次。除以10万,平均2000 QPS。流量不会均匀到来,所以把峰值按平均值的2到3倍来算,取5000到6000 QPS作为设计基准。当你说出读写比假设为100比1的那一刻,缓存和只读副本的话题就毫不牵强地跟了上来。

存储也是同样的做法。一条文本帖子1KB,一天一百万条,就是一天1GB,一年365GB。保存五年再做三副本,大约5.5TB。这时候如果加上图片,数量级就变了。平均200KB的图片一天一百万张,就是一天200GB,一年73TB。只有算过这笔账的人,才能带着依据说出"图片分离到对象存储,数据库里只放元数据"这句话。

估算里被打分的不是精确度,而是你有没有把假设摆到台面上。1000万这个数字错了也没关系。只要你说过"用户1000万、人均20次、峰值3倍",面试官就能当场帮你改数字,从那一刻起两个人就在解同一道题了。

最常翻车的四个地方

  • 不问需求就先画图。最常见也最致命。一天一万次的系统和一天十亿次的系统完全是两种东西,不问就开工,画出来的会是两边都不是的东西。前五分钟至少要把这四项定下来:规模、读写比、延迟目标、一致性要求的级别。
  • 罗列流行技术。把Kafka、Redis、Elasticsearch、Kubernetes全摆在一张图上,然后用"我会这样搭"收尾。面试官问"如果没有这个队列会怎样"而你答不上来,那个方框就不是加分而是减分。每画一个组件,就给它配上一句话,说明它消除了什么问题。
  • 不给代价就下断言。"我会用NoSQL""我会走微服务"这类句子,本身从来不构成答案。这里如果能准确地处理CAP定理,印象会大不一样。这个命题由Eric Brewer在2000年作为猜想提出,2002年由Gilbert和Lynch给出证明,常被概括成"三选二",但Brewer本人在2012年的文章里更正过,说这种概括会引起误解。准确的表述是只有在网络分区真的发生时,才必须在一致性和可用性之间做出选择,而平时两者都可以在相当高的水平上同时拥有。
  • 在深挖环节停留在表面。面试官说"这部分我们再多看一点"的那一刻,就是分数的重心。这时候把话题转到别的组件上,会被读成回避。值得准备的常客话题是固定的那几个:分片键的选择与热点、缓存失效与击穿、幂等性与重试、不重复的ID生成,还有尾延迟。

怎么把"我不知道"说好

碰到不知道的东西不是意外,而是设计。一道45分钟的开放题里如果没有出现你不懂的段落,那说明题目太简单了。所以要准备的不是"怎么避开不懂的场面",而是"用什么句子处理不懂的场面"。

分成三部分来说,几乎永远是安全的。承认边界,用已知的原理做推理,再给出验证的方法。

"Kafka的精确一次投递我自己没有实际运维过。从原理推,应该需要生产者幂等和事务提交一起工作,而一旦把消费端的处理也算进来,最后大概还是需要应用层的幂等。实际落地时我会先看文档和压测结果再决定。"

这个回答拿到的不是知识分,而是校准分。能把知道和不知道之间的界线画准的人,在生产环境里做出危险决策的概率更低。面试官看的就是这个。反过来,最糟的两种应对是:装懂然后在第二个追问上崩掉,以及用一句"不知道"把对话掐断。

越是压力大的瞬间,这句话越说不出口。面试中真正崩掉的地方,不是不知道这件事本身,而是为了掩饰不知道而挣扎的那几分钟。在那几分钟里,思考停住了,语速却变快了。训练这种反应的原理,和在高压场合不崩盘的方法里讲的压力接种是一样的。除了在接近实战的条件下先晃一晃,没有捷径。

而且这场面试有一半,归根结底是对话。比起一个人念念有词地把图画完,能看着对方反应调整速度的人分数更高。会聊天究竟是什么里讲的原则,在白板前照样有效。

结语 — 被打分的不是结论,而是收敛的过程

回想系统设计面试发挥得好的那些日子,通常并不是画出华丽架构的那天。而是把五条需求砍成两条、把数字算了三遍、把某一点挖到底的那天。图反而是简单的。

准备也可以朝同一个方向。与其把十道题扫一遍,不如挑三道计时、出声地各做45分钟。而且每一次都用最后五分钟问自己这个问题:今天我放弃了什么,又为什么判断可以放弃它。这个答案理清多少,实力就长多少。

현재 단락 (1/43)

有一个常见场景。面试官刚说完"请设计一个短链服务",候选人就拿起了笔。客户端、负载均衡、Web服务器、数据库。五个方框六条箭头,三分钟就画完了。然后大约过了25分钟,面试官问:"一天需要处理多少请求?...

작성 글자: 0원문 글자: 3,823작성 단락: 0/43