很多软件工程师在系统设计面试(SDI)中挣扎,主要是因为三个原因:
• SDI的非结构化特性,要求面试者进行开放式设计但是却没有标准答案。
• 面试者缺乏开发大型系统的经验。
• 面试者没有为SDI做准备。
像编码面试一样,那些没有有意识地为SDI做准备的应聘者,大多是表现不佳,尤其是在谷歌、Facebook、亚马逊、微软等顶级公司公司,即表现不高于平均水平的候选人,获得录用的机会有限。另一方面,一个好的表现总是带来更好的工作机会(更高的职位和薪水),因为显示候选人处理复杂系统的能力。
在本课程中,我们将循序渐进地解决多个设计问题。
首先,我们通过以下步骤:
第一步:需求背景说明(3W-whenwherewhy)
这里其实类似一个如何写一个系统设计文档或者需求文档,需要将背景交代清楚,什么条件前提下?基于什么样的考虑背景。因为要记住一点的是,系统设计并不是一开始就非常完美的,但是它却是简单、合适、可持续的,在平衡取舍当下系统情况下做的抉择。---- 小诚信驿站注
针对我们正在解决的问题的确切范围提出问题会比较好(现状痛点
)。设计问题大多是开放式的,他们没有一个正确的答案,这就是为什么要说明背景情况的重要性(平衡取舍结果-更多是基于特定场景的特定方案,不一定是最完美的但是是最合适的
)。
在面试的早期模棱两可就变得至关重要了(项目讲述不清的话基本上说明对系统没能掌控基本上会被淘汰
)。花足够的时间定义系统的最终目标总是有更好的机会在面试中获得成功。还有,既然我们只有35-40分钟的时间来设计一个(假设)大型系统,我们应该弄清楚系统的哪些部分是
我们将关注的。(核心模块-抽象建模能力,也就是你的系统的核心建模-核心指标,目的是建模要解决上面说的痛点
)
让我们用一个设计类似于Twitter的服务的实际例子来扩展这一点。这里有一些问题对于设计在进入下一步之前应该回答的问题:
•我们服务的用户是否能够发布推特并跟踪其他人?
•我们是否也应该设计来创建和显示用户的时间线?
•推特会包含照片和视频吗?
•我们是只关注后端还是也在开发前端?
•用户是否能够搜索推文?
•我们是否需要展示热门话题?
•是否会有推送新(或重要)推送通知?
所有这些问题都将决定我们的最终设计。
第二步:系统接口定义
定义系统需要哪些api。这不仅能确定预期的确切接口协议,而且从系统也将确保我们不会得到任何要求错误。我们类似Twitter的服务的一些例子将是:
postTweet(user_id, tweet_data, tweet_location, user_location, timestamp, …)
generateTimeline(user_id, current_time, user_location, …)
markTweetFavorite(user_id, tweet_id, timestamp, …)
第三步:规模估算
估计我们要设计的系统的规模总是一个好的建议。这也会有帮助稍后我们将重点讨论扩展、分区、负载平衡和缓存。
•系统的预期规模(例如,新tweet的数量、tweet视图的数量,每秒的时间线生成数(等等)?
•我们需要多少存储空间?我们将有不同的号码,如果用户可以有照片和他们推特上的视频。
•我们期望的网络带宽使用率是多少?这将是决定我们将采取何种行动的关键管理流量并平衡服务器之间的负载
第四步:定义数据模型(抽象建模-实体、属性、联系
)
尽早定义数据模型将阐明数据将如何在系统的不同组件之间流动系统。稍后,它将指导数据分区和管理。候选人应该能够识别系统的各种实体,它们将如何相互作用,以及系统的不同方面存储、传输、加密等数据管理服务:
User: UserID, Name, Email, DoB, CreationData, LastLogin, etc.
Tweet: TweetID, Content, TweetLocation, NumberOfLikes, TimeStamp, etc.
UserFollowo: UserdID1, UserID2
FavoriteTweets: UserID, TweetID, TimeStamp
我们应该使用哪个数据库系统?像Cassandra这样的NoSQL最适合我们的需要,还是我们应该使用它类似MySQL的解决方案?我们应该使用什么样的块存储来存储照片和视频?
第五步:高级别设计
画一个方框图,5-6个方框代表我们系统的核心组件。我们应该确定从端到端解决实际问题所需的足够组件。 对于Twitter来说,在高层次上,我们需要多个应用服务器来服务所有的读/写操作 前面有负载平衡器的请求用于流量分布。如果我们假设我们会如果有更多的读流量(与写流量相比),我们可以决定使用单独的服务器来处理这些场景。在后端,我们需要一个高效的数据库,可以存储所有的推文和可以 支持大量读取。我们还需要一个用于存储照片的分布式文件存储系统还有视频。
第六步:详细设计
深入研究两个或三个组成部分;面试官的反馈应该总是指导我们工作的哪些部分?这个制度需要进一步讨论。我们应该能够提出不同的方法,它们的优点和缺点,并解释为什么我们会选择一种方法而不是另一种方法。记住,没有单一的答案,唯一重要的是在保留系统的同时考虑不同选项之间的权衡考虑到约束。
•由于我们将存储大量数据,我们应该如何将数据划分为是否将其分发到多个数据库?我们是否应该尝试将一个用户的所有数据存储在同一个服务器上数据库?会引起什么问题?(分布式数据库,分库分表,数据一致性
)
•我们将如何处理那些经常发推特或关注很多人的热门用户?(热数据问题
)
•由于用户的时间线将包含最新(和相关)的推文,我们是否应该尝试存储我们的数据在这样一种方式,是优化扫描最新的推特?(异构数据表
)
•我们应该在多大程度上以及在哪一层引入缓存来加快速度?(缓存
)
•哪些组件需要更好的负载平衡?(负载均衡
)
第七步:识别和解决技术难点
尝试讨论尽可能多的瓶颈以及缓解瓶颈的不同方法。
•我们的系统中是否存在单点故障?我们在做什么来减轻它?(单点故障
)
•我们是否有足够的数据副本,以便在丢失一些服务器的情况下仍能为客户提供服务用户?(副本备份
)
•类似地,我们是否有足够的不同服务运行副本,以避免出现一些故障不会导致系统完全关闭吗?(容灾
)
•我们如何监控服务效果?关键时刻我们会收到警报吗?组件失效或性能下降?(监控
)
第八步:归纳总结
总之,面试过程中的准备和组织是面试成功的关键,设计面试。上述步骤应指导您保持正轨,涵盖所有 设计一个系统时要考虑不同的方面。 让我们应用上述准则来设计SDIs中要求的几个系统。
资料来源: