2-23 浅谈系统设计(1)

很久很久没有更新了。这段时间写了不少无脑的回答,大概是因为这半年有些累,提不起精神来。这里感慨一句:技术上,可以说真的是一分积累,一分耕耘,一分收获,半点马虎不得——过去的120年里,总有人试图用刀枪不入这种“邪术”抵抗洋枪洋炮的“正道”。


我觉得学技术之所以简单,就是因为不需要邪术,只要无脑走正道硬碰硬即可。有人问:改行者如何能达到科班的水平?正道的回答简单而又残酷:科班学什么,改行者学什么,自然水平会上来。——想规避时间和努力花费,是不现实。


系统设计这个话题极大,并且高端。如果粗略估计,100个码工中,大概也只有20个左右粗窥门径的,里面专精者,不过3、5人而已。


并且,这些人大量集中在一线公司以及互联网企业,并不是均匀分配的。传统IT企业,哪怕工作10年以上的人,系统设计依然可能很弱很弱。


为什么要了解系统设计

有人说自己没那么高的追求、没必要去学系统设计。这话不见得错。系统设计实在不是人人能掌握的、人人需要掌握的。


然而,抛开追求不谈,系统设计或许将成为择优的一个重要因素。换句话说,计算机行业人满为患,如何筛选技术人才?


第一,刷题;

第二,系统设计;


以Google的面试为例,5级(资深)的工程师面试是5轮,3轮写代码,1轮Behavior Question(行为面试,2019年新加的),1轮系统设计。可见,系统设计至少占着20%的重要性。


要知道,刷题和系统设计,本质上还是择优、用来刷人。比如工程师写IOS的,Android的,做前端的,面系统设计并没有太多实际意义;然而,想来的人,合适的人,实在是太多了,没法筛选,那么系统设计自然可以用来区分。


跟高考一样——录取分数并不跟大学需要的知识相关,只跟同一个省的竞争者有关。

什么是系统设计

这个问题很难回答,非顶端大牛不可定义。各位可以自己搜索和看各种视频,教程。与其纠结于定义,不如讲讲它的作用、地位。但这也颇难,所以我只能搬运些别人的话,加上自己的理解。


这个课程是我非常推荐的:

69美元,我买过,并且过了Facebook的面试。我只买过这个和LeetCode。如果实在不想花钱,可以看它给的免费sample(样品)部分,也是很有收获的。


它在开篇就讲了系统设计的意义:

“System design questions have become a standard part of the software engineering interview process. Performance in these interviews reflects upon your ability to work with complex systems and translates into the position and salary the interviewing company offers you. Most engineers struggle with the system design interview (SDI), partly because of their lack of experience in developing large-scale systems and partly because of the unstructured nature of SDIs. Even engineers who’ve some experience building such systems aren't comfortable with these interviews, mainly due to the open-ended nature of design problems that don't have a standard answer. ”

我帮着翻译解释下重要部分:

“Performance in these interviews reflects upon your ability to work with complex systems and translates into the position and salary the interviewing company offers you.”说的是,系统设计反映出的,是一个工程师工作在复杂系统上的能力,并且决定了给offer的职位和工资。


其实,美国人的教程都开门见山地指出了系统设计面试的核心:工资和职位。简单来说:


  1. 刷题能力决定了一个人是否能够拿到Offer
  2. 系统设计能力决定了一个人拿到的Offer的级别,以及同级别下的钱多少


要知道,湾区这种大厂遍地的环境下,进入一线大厂并非难事只要有毅力和体力,但进入一线大厂,并且拿到满意的级别,和这个级别最佳的工资,才是比较困难的。这里,系统设计的意义就明显体现出来了。


“Most engineers struggle with the system design interview (SDI), partly because of their lack of experience in developing large-scale systems and partly because of the unstructured nature of SDIs. ”

这里说的是绝大多数工程师都在系统设计上非常困苦,大概因为:(1)缺乏大尺度系统的经验;(2)系统设计知识本身就是零散、非结构性的;


先说(1)缺乏大尺度系统的经验

我过了面试加入公司后,最大的感慨就是原来在没进FB时不理解、死记硬背的系统设计知识,原来是如此的自然和容易——所谓难者不会、会者不难。那些看似无厘头的问题,其实正是每一个实际存在和要解决的系统问题。


然而,我当初不懂,是因为笨吗?是因为不努力吗?不是。这明显是个蛋生鸡鸡生蛋问题——大部分人没做过具体的large-scale的项目,因为只有互联网公司有large-scale的生态环境,所以大部分人不会;但互联网公司又考察这些,所以就过不了面试。越是不会,越进不去,越进不去,越是不会;而在互联网公司工作的人,却每天在积累这种系统经验。


于是,结果一定是:只有少数工程师,越来越精通系统设计;大部分人,因为没有机会,还处于纸上谈兵阶段。


再说(2)系统设计知识本身就是零散、非结构性的

系统设计是最贴近工作现实的,比算法题、OOD等都要贴近。因此,系统设计的各个主题,都是实际工作中碰到的问题,因此异常现实,但知识体系就非常零碎。


比如Key-Value Pair这个概念。本身在算法中就是极其重要的,在系统设计中其实可以解决相当多的Performance相关的问题。KV的系统,KV的Cache,基本上是很多系统的标配。但这并没有一个非常成体系的学习过程,所以新手读起来非常困惑:为什么要这样。


更别说不同种类的数据库以及它们能解决的问题了。


我搜遍了网上,并没有太好的、成体系的系统设计教程。我开头给出的那个课程,我觉得已经相当翔实了——虽然具体某些设计,其实未必正确。



接下来再看这段“Even engineers who’ve some experience building such systems aren't comfortable with these interviews, mainly due to the open-ended nature of design problems that don't have a standard answer. ”


这段就说得更狠了:即使有相关经验,也未必能做得好,因为系统设计是没有一个正确答案的、开放性问题。


即使接触过large-scale系统的工程师,又如何呢?如果没有广度和深入的思考,也会fail系统设计面试,因为这个是开放性问题——必须加强交流,跟面试官保持同步思考,使得人满意。


比如懂KV的,未必懂Messaging;懂Video Streaming的,未必懂地图是如何设计的;懂Indexing、Search的,又未必懂得Cache。面试官随便一个小问题,都可能把人问晕。


所以,这不仅仅是个深度广度都有的问题,更是一个交流、猜测对方的期望和知识结构的过程。这可以说就难上加难了。



总结一下,系统设计大概可以认为是:

  1. 设计一个大尺度(large-scale)而复杂的系统
  2. 给出各种没有标准答案的解,并且在面试中表现出自身强大的计算机知识修养,以及敏锐的系统感觉


所以,相比于刷题,系统设计更看重的是:

  1. 实际工作经验,如果没有实际经验,则看这个人的学习能力了
  2. 知识的深度和广度


解释一下:如果有实际的工作经验当然好,但没有(毕竟大多数人都没有),那么就很看这个人学习、收集、整合知识的能力了。LeetCode虽然难刷,但是只要按部就班终究有精通的那天;系统设计则不然,如何整合各种杂乱的资料,如何通过阅读网络已经公开的设计来理解系统,是很困难的。


此外,系统设计要求人对计算机的知识有深度和广度。以这个github上著名的《Latency Numbers Every Programmer Should Know》为例:


新手肯定看得一头雾水:我需要记这些数字么?


并不是如此。但是比如这一条:

Read 1 MB sequentially from SSD* 1,000,000 ns 1,000 us 1 ms ~1GB/sec SSD, 4X memory


大概是说从SSD上读连续的1MB数据,需要1ms(一毫秒)。这个就值得记住,因为可以描述了SSD大概有多快。设计高并发、快速读写的系统时,可以内心中有个数量概念。


再比如:

Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms

是说package从加州,到尼德兰,再返回加州需要150ms。如果懂得Data Center知识的人,就知道当加州或是美国的数据中心(Data Center)发生灾难时(洪水、地震、断电),加州依然可以跨大陆使用位于欧洲尼德兰的数据中心,但速度要慢上150ms。


所以这些知识,课本上或许会教,但是非常零散,并且知识体系没有成型时,根本不知道哪些知识会用在哪里。



那么,是否有“捷径”和好的办法呢?


答案当然是没有。“真正”懂系统设计的码工,所占比例是很少的;而这些人大部分都在大厂担当核心职位或是非常舒服的职位,根本没有心情去教课。加上种种原因,可以说公开的、免费的资料是相当杂乱的,而哪怕收费的系统设计资料,也不甚精深。


好在,要知道系统设计的面试是择优过程。100分满分,平均30分并不说明什么,只能说题太难了,那么只要争取自己能到35分甚至40分,就足够了。


真正的现实面试中,各种令人笑掉大牙甚至违反基本原则的设计不少见。所以,系统设计面试带来的是开放性竞争——并不需要设计出完美的答案和系统,只要比大多数人强,就足够了。

发布于 2019-09-10 13:55