系统设计是面试当中的一个常考点,是面试官考察面试者知识广度与深度最直接的方式。
许多开发者在系统设计面试中痛苦主要是因为下面三个原因
- 系统设计面试属于开放性问题,没有一个标准的答案
- 缺乏开发大规模系统的经验
- 对系统设计问题没有准备
就像代码面试一样,那些没有有意识地为系统设计面试做准备的求职者,大多表现不佳,尤其是在谷歌、Facebook、亚马逊、微软等顶级公司的面试中。在这些公司中,表现不佳的求职者得到录用的机会非常有限。另一方面,良好的表现总是会带来更好的待遇,因为这显示了候选人处理复杂系统的能力。
第一步 需求分析
对我们要解决的问题确切范围
并且提出问题
。设计类问题大多是开放式的,它们没有一个正确的答案,这就是为什么在面试中尽早澄清模棱两可的问题变得至关重要。花足够时间定义系统最终目标的候选人总是有更好的机会在面试中取得成功,此外,由于我们只有35-40分钟的时间来设计一个大型系统,我们应该明确我们将重点关注系统的哪些部分。
让我们用一个设计类似twitter的服务来扩展这一点。以下是一些设计Twitter时应该首先明确的问题。
- 用户能够发布推文并关注其他人吗?
- 我们应该设计创建和显示用户的时间轴吗?
- 推文会包含照片和视频吗?
- 我们是只关注后端还是也开发前端?
- 用户能够搜索推文吗?
- 我们需要展示热门话题吗?
- 我们需要设计新的(或重要的)推文推送通知吗?
这些问题将会决定我们的系统最终设计会是什么样子。
第二步 系统接口定义
定义系统所需要的API,这不仅可以建立系统预期的确切规范,而且还可以确保我们没有弄错任何要求。 下面是我们类似Twitter服务的一些接口示例:
第三步 规模估计
估计我们要设计的系统的规模,有助于我们以后关注扩展、分区、负载平衡和缓存。
- 系统的预期规模(例如,新推文的数量,推文的浏览数量,每秒钟时间轴的生成数量,等等)
- 我们需要多少存储空间? 如果用户可以在推特上上传照片和视频,我们会有不同预期的存储空间。
- 我们期望的网络带宽使用量是多少? 这对于决定我们将如何管理流量和平衡服务器之间的负载至关重要。
第四步 定义数据模型
尽早定义数据模型将阐明数据如何在系统的不同组件之间流动。之后,它将指导数据分区和管理。候选人应该能够识别系统的各种实体,它们将如何相互作用,以及数据管理的不同方面,如存储、传输、加密等。这里有一些我们的Twitter服务的实体定义。
我们应该使用哪个数据库系统? 像Cassandra这样的NoSQL是否最适合我们的需求,或者我们应该使用类似mysql的解决方案? 我们应该使用什么样的块存储来存储照片和视频?
第五步 高层次设计
用5-6个框图表示我们系统的核心组件。我们应该确定从端到端解决实际问题所需的足够多的组件。对于Twitter,在较高级别上,我们将需要多个应用程序服务器来处理所有读/写请求,并在它们前面使用负载均衡器进行流量分配。 如果我们假设我们将有更多的读取流量(与写入相比),我们可以决定使用单独的服务器来处理这些场景。在后台,我们需要一个高效的数据库来存储所有的tweet并支持大量的读取。我们还需要一个分布式文件存储系统来存储照片和视频。
第六步 详细设计
深入挖掘系统的两三个组件,根据面试官的反馈来确定面试官更关心系统中哪部分的实现,并且进行进一步的讨论。我们应该能够提出不同的方法,它们的优缺点,并解释为什么我们更喜欢一种方法而不是另一种方法。记住,没有单一的答案,唯一重要的事情是考虑不同选项之间的权衡,同时牢记系统约束。
- 由于我们将存储大量的数据,我们应该如何划分数据以将其分布到多个数据库?我们是否应该尝试将一个用户的所有数据存储在同一个数据库中?它会引起什么问题呢?
- 我们将如何处理推特或关注很多人的热门用户?
- 既然用户的时间线将包含最新的(和相关的)tweets,我们是否应该尝试以一种优化的方式存储我们的数据,以扫描最新tweets?
- 我们应该在哪个层引入多少缓存来加速呢?
- 哪些组件需要更好的负载平衡?
第七步 瓶颈问题
尝试讨论尽可能多的瓶颈和不同的方法来缓解它们。
- 我们的系统有单点故障吗? 我们要做什么来减轻它?
- 我们是否有足够的数据副本,以便在失去一些服务器时仍能为用户提供服务。
- 类似地,我们是否有足够多的不同服务的副本在运行,以便一些故障不会导致整个系统关闭。
- 我们如何监控服务的表现? 当关键组件出现故障或性能下降时,我们是否会收到警报。
总结
总之,面试过程中的有准备和有组织是系统设计面试成功的关键。上述步骤将指导您在设计系统时保持跟踪并涵盖系统设计的不同方面。