系统设计是为了满足特定需求,定义计算机系统内构架,模块,接口和数据的过程。这是每一个后端或者全栈工程师的必修课,随着工作年限的增长和项目的扩大,系统设计在日常工作的重要性会不断增加。
如果你想跟罗辑一起更深入地学习系统设计,有兴趣的同学报名参加爱思备受好评的系统设计集训营以及系统设计模拟面试,由作者本人为同学们教学,力求给大家带来最深入的系统设计高频题讲解以及最针对面试实战的技巧解析,帮助同学们举一反三,高效准备面试。
1. 为什么要考系统设计面试?
实际意义大
跟算法面试类似的,面试官需要能从人群里分辨出谁更适合所招聘的职位。系统设计作为日常工作中会经常用到的能力,在考察中有很强的现实意义。可以想象,如果一个组里需要找资深工程师来帮助升级服务的构架,系统设计能力会决定岗位的归属。
区分度高
系统设计面试可以看出受试人对问题多方面的理解,不同水平的受试人对于问题的广度和深度会有很大差异,很大程度上帮助面试官了解受试人的能力以及确定未来职位的级别。
2. 系统设计考什么?
- 交流沟通和理解能力 - 跟面试官充分交流理解所设计系统的目标,方便做设计中的tradeoff,在厂里干过的就知道日常工作中这个非常重要
- 设计和架构能力 - 很多我见过的面试者都只注重在这块而忽略了其他,很可惜
- 扩展性 (Scalability),容错性,延迟要求 - 跟Operation相关的要求,如今Dev和Ops不分家,希望面试者了解系统今后能如何扩展,易于maintain
- 资源需求 - 对于我们所要求的QPS和latency,需要多少台机器,其中CPU, 内存,硬盘等资源都是如何配置
当然,以上四点,根据同学们的实际情况,并不用在每一点上都给出完整的回答,面试官会在面试过程中指出深挖的方向,有可能是根据同学的专业或者职业背景,有可能是根据所面试的岗位,有可能是根据面试中同学提到的他熟悉的技术。
3. 怎样答好系统设计题?
在面试生涯中,见过的最优秀的面试者比我的级别要高,让我印象非常深刻,四个字,深不见底。
面试的前半段,面试官会先从广度下手,要求受试者对题目的大框架给出一个完整的正确的解法。如果受试者给出了足够好的解法,那么面试官会从受试者的提过的某一个细部进行深挖,可能是深挖scalability,可能是改变一个需求要求重新做tradeoff,可能是某一个service的细节设计。因为其中的细节足够多,受试者一般很难准备得面面俱到,面试官可以比较清楚的画出受试者的能力边界。前面提到的这个受试者之所以让我感到深不见底,是因为我才疏学浅,画不出他的能力边界,不得不赞叹大神,在debrief中好好膜拜了一番。 说了这么多,还是想说平时的积累很重要,面试速成能够让你在广度上做的很好,深度方面还是要多花时间学习。
讲完了废话,讲一些可以操作性强的,我们结合考察内容,对优秀回答的特征做进一步表述。
交流沟通和理解能力
- 询问系统的商业目的 - 建这个系统是为了解决什么问题。相关的问题比如这个服务的受众有什么特点,是商业用户还是个人用户。很多时候问不问这个问题就能看出Senior的程度。
- 询问功能性需求 (functional requirement) - 包含哪些子功能。
- 确定非功能性需求 (non-functional requirement) - 我们要总结说我们在面试结束前我们的设计要达到什么QPS,latency或者availability指标。写下来并跟面试官确认。如果这里牵涉到一些ballpark calculation,跟面试官确认是不是需要算。
- 整场面试过程中跟着面试官的引导走- 有的同学看到准备过的题就很兴奋,文思泉涌面试官都拉不住,会让人觉得理解能力不足
设计和架构能力
这是正常面试的核心部分,非常重要,是面试通过的基础,其中deep dive非常考验真实水平。讨论过程中记住要保证设计的完整性,正确性以及取舍的充分沟通。答题点主要分成以下五大块。
- High-level diagram
- 数据结构与存储
- 核心子服务设计
- 接口设计
- 专题 deep dive
扩展性,容错性,延迟要求
- 确认系统在以上三点 Scalability, Fault Tolerance, Latency Requirement是否符合先前定下的需求。
- 根据需求进行改进(推荐在第一轮设计中先不考虑这里的三点,先拿下设计和架构能力的分数,再做改进)
- Log,monitor and alert on key metric (系统投入使用前,把非功能性需求和它的leading indicator确定下来并且做好监控)
资源估算(optional)
估算非功能性需求,计算需要多少台机器,需要多少内存,硬盘,带宽和CPU的能力,量级正确即可(back of envelope calculation)。
5. 答题流程 + 时间分配
面试中常见的错误是答题流程松散,在不必要的话题上浪费时间。我见过不计其数的受试者纠结于一个特定话题导致没有时间完成面试的主体部分。我们来看看怎么避免这类错误。
形成固定的答题流程的作用有二。一是引导面试官进入你的答题框架,二是用固定的流程保证不漏过重要的得分点。
引导面试官
虽然面试官在系统设计面试中有比算法面试更强的引导的责任,但是引导的行为只有在需要的时候才会发生。如果一场面试中,总是受试者提问,面试官回答,受试者滔滔不绝地讲,面试官连连点头,画面是不是很美?虽说前面的情景很理想化,但是如果我们能很好地把面试官想踩到的点按一个大概的顺序去踩到,不仅面试官会更少地打断受试者的思维,而且面试官也会在面试中很省力给你个好印象。当然,如果引导发生了,那么一定要根据引导来思维。
答题流程
以40分钟的面试时间来算(掐头去尾除去自我介绍问问题),我面试的大概流程如下。
- 【3分钟】理解需求 (询问系统的商业目的 + 询问系统的功能和技术需求 + 定义成功)
- 【0-5分钟】资源估算(optional)(计算需要多少台机器,需要多少内存硬盘和CPU的能力)
- 【5分钟】High-level diagram
- 【5分钟】数据结构与存储
- 【10分钟】核心子服务设计
- 【5分钟】接口设计
- 【5分钟】扩展性,容错性,延迟要求
- 【2-7分钟】专题 deep dive
注意几点,4,5,6顺序没太大关系。8可以考虑成额外分数,答对大量加分,答错少量减分,如果没时间会跳过,也是少量减分。
看完这个流程是不是感觉分秒必争,要踩的点很多,没有时间浪费。这时候如果面试官听出来某一步骤有错误,就算是回头改对了,浪费的时间也会造成一些本能踩到的点因为时间不足踩不到,所以大家还是好好准备,刷算法题之余也把系统设计重视起来。