众所周知,系统设计在程序员面试中的占比仅次于coding,所以学好系统设计,心仪的offer基本稳了一半学习的过程中,我建议采用一个 7 步框架来解决每个问题。为了保持示例的真实性,我们将提出一个常见的面试问题:设计一个可扩展的服务,如 Twitter,看看每个步骤如何应用于设计 Twitter。
第 1 步:需求收集:
许多候选人认为系统设计访谈都是关于“规模”的,忘记把重点放在“系统”部分。在扩展之前,需要有一个可用的“系统”。
作为面试的第一步,你应该提出问题以找出问题的确切范围。设计问题大多是开放式的,他们没有一个正确的答案。这就是为什么在面试的早期澄清含糊不清的原因变得至关重要。花时间明确定义系统最终目标的候选人总是有更好的成功机会。
以下是设计 Twitter 的一些问题,在继续下一步之前应该回答这些问题:
1.谁可以发推文? (回答:任何用户)
2.谁可以阅读推文? (回答:任何用户 - 因为所有推文都是公开的)
3.推文是否包含照片或视频(答案:现在,只是照片)
4.用户可以关注其他用户吗? (回答:是)。
5.用户可以“喜欢”推文吗? (回答:是)。
6.用户提要中包含哪些内容(答案:你所关注的所有人的推文)。
7.按时间顺序提供推文列表吗? (回答:现在,是的)。
8.用户可以搜索推文(回答:是)。
9.我们是设计客户端/服务器交互还是后端架构或两者兼而有之(答案:我们想要理解客户端/服务器之间的交互,但我们将关注如何扩展后端)。
10.有多少用户(答案:我们预计第一年将达到 2 亿用户)。
11.有多少每日活跃用户(每天有 1 亿用户登录)
如果你注意到,这些答案中的一些与真正的 Twitter 并不完全相似,那没关系。这是一个旨在评估方法的假设问题。你只是要问这些问题,以确定今天要解决的问题。不必担心使用算法等处理视频或生成时间栏。
第 2 步:系统接口定义
如果你已经收集了需求并且可以识别系统公开的 API,那么完成了 50%。
定义系统所需的 API。这不仅可以确定系统预期的确切合同,而且还可以确保你没有遇到任何错误的要求。我们类似 Twitter 的服务的一些例子是:
postTweet(user_id,tweet_text,image_url,user_location,timestamp,...)
generateTimeline(user_id,current_time)
recordUserTweetLike(user_id,tweet_id,timestamp,...)
第 3 步:封装容量估计
估计设计的系统的规模总是一个好主意。当你专注于扩展,分区,负载平衡和缓存时,这也会有所帮助。
1.系统预期的比例(例如,新推文的数量,推文视图的数量,每秒的时间线生成次数等)
2.我们需要多少存储空间?这取决于用户是否可以在推文中上传照片和视频?
3.我们期望的网络带宽使用量是多少?这对于决定如何管理流量和平衡服务器之间的负载至关重要。
第 4 步:定义数据模型
尽早定义数据模型将阐明数据如何在系统的不同组件之间流动。稍后,它将指导你进行更好的数据分区和管理。候选人应该能够识别系统的各种实体,他们将如何相互交互以及数据管理的不同面,如存储,传输,加密等。以下是我们类似Twitter 的服务的一些实体:
User:UserID,Name,Email,DoB,CreationData,LastLogin 等.
Tweet:TweetID,Content,TweetLocation,NumberOfLikes,TimeStamp 等.
UserFollows:UserdID1,UserID2FavoriteTweets:UserID,TweetID,TimeStamp
我们应该使用哪个数据库系统?像Cassandra这样的NoSQL最适合我们的需求,或者我们应该使用类似 MySQL 的解决方案。我们应该使用什么样的 blob 存储来存储照片和视频?
第 5 步:高级设计
绘制一个框图,其中包含 5-6 个框,代表系统的核心组件。你应该确定从端到端解决实际问题所需的足够组件。
对于 Twitter,在高层次上,我们需要多个应用程序服务器来为所有读/写请求提供服务,并在它们前面设置负载均衡器以进行流量分配。如果我们假设我们将拥有更多的读取流量(与写入相比),我们可以决定使用单独的服务器来处理读取 vs 写入。在后端,我们需要一个高效的数据库,可以存储所有的推文,并可以支持大量的读取。我们还需要一个分布式文件存储系统来存储照片(和视频)以及搜索索引和基础设施,以便能够搜索推文。
第 6 步:所选组件的详细设计
深入挖掘2-3个组件;面试官的反馈应该始终指导你进一步解释系统的哪些部分。你应该能够提供不同的方法,它们的优点和缺点,为什么你会选择一个?请记住,没有一个答案,唯一重要的是考虑不同选项之间的权衡,同时牢记系统约束。例如
1.由于我们将存储大量数据,我们应该如何对数据进行分区以将其分发到多个数据库?我们是否应该尝试将用户的所有数据存储在同一个数据库中?它会导致什么问题?
2.我们如何处理高流量用户,例如拥有数百万粉丝的名人?
3.由于用户的时间线将包含最新(和相关)的推文,我们是否应该尝试以优化的方式存储我们的数据以扫描最新的推文?
4.我们应该在多大程度上引入缓存以加快速度?
5.哪些组件需要更好的负载平衡?
第 7 步:识别并解决瓶颈问题
尝试讨论尽可能多的瓶颈和不同的方法来缓解。
1.我们的系统中是否有任何单点故障?我们在做什么来减轻它?
2.我们是否有足够的数据副本,这样如果我们丢失了一些服务器,我们仍可以为用户提供服务?
3.同样,我们是否有足够的不同服务副本运行,这样一些故障不会导致整个系统关闭?
4.我们如何监控服务的表现?当关键组件发生故障或性能下降时,我们会收到警报吗?
简而言之,由于软件设计访谈的非结构化特性,组织有明确计划来解决问题的候选人有更好的成功机会。
关于其他系统设计,其实都可以套用这七步解题法,当然,还有更多系统设计解题秘诀,可以戳这里免费领取哦!