# 系统设计演进指南

### 系统设计访谈：演进指南

很多人纠结于系统设计访谈(sdi)主要是因为1)结构化sdi的本质,要求你工作的地方在一个开放式的设计问题没有标准答案,2)你在开发大型系统缺乏经验,3)你不花足够的时间来准备sdi。

就像编写面试程序一样，没有花时间准备sdi的求职者大多表现不佳。当你在谷歌、Facebook、Uber等顶级公司面试时，这种情况就更严重了。在这些公司中，如果求职者的表现没有超过平均水平，他们获得录用的机会就非常有限。另一方面，良好的表现总是会带来更好的机会(更高的职位和薪水)，因为它反映了你处理复杂系统的能力。

在本课程中，我们将遵循一步一步的方法来解决多个设计问题。以下就是这七个步骤:

### Step 1: 需求澄清

经常问问题，以找到你要解决的问题的确切范围。设计问题大多是开放式的，并且没有一个正确的答案，这就是为什么在面试的早期澄清模糊是非常重要的。花足够的时间明确系统的最终目标的候选人，总是有更好的机会在面试中成功。此外，因为你只有35-40分钟的时间来设计一个大型系统，所以你应该明确你将专注于该系统的哪些部分。

在每一步中，我们将尝试给出开发类似twitter的服务时需要考虑的不同设计因素的例子。

以下是一些关于设计Twitter的问题，在进入下一步之前应该回答的问题:

● 我们服务的用户能够发布推文并关注他人吗?

● 我们是否也应该设计创建和显示用户的时间轴?

● 推文会包含照片和视频吗?

● 我们是只专注于后端还是也开发前端?

● 用户能够搜索tweet吗?

● 我们需要显示热门的热门话题吗?

● 对于新的(或重要的)推文，会有推送通知吗?

所有这些问题将决定我们的最终设计将是什么样的。

### Step 2: 系统接口定义

定义期望系统提供哪些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, …)
```

### Step 3: 粗略估计

估计你要设计的系统的规模总是一个好主意。当你以后关注于扩展、分区、负载平衡和缓存时，这也会有所帮助。

● 系统的预期规模是多少(例如，新推文的数量，推文浏览的数量，每秒钟产生多少时间轴代，等等)?

● 我们需要多少存储空间?如果用户的推文里有照片和视频，我们就会有不同的号码。

● 我们期望的网络带宽使用是多少?这对于决定如何管理流量和平衡服务器之间的负载至关重要。

### Step 4: 定义数据模型

早期定义数据模型将阐明数据如何在系统的不同组件之间流动。稍后，它将指导数据分区和管理。候选人应该能够识别系统中的各种实体，它们如何相互作用，以及数据管理的不同方面，如存储、传输、加密等。以下是我们类似twitter的服务的一些实体:

```
User: UserID, Name, Email, DoB, CreationData, LastLogin, etc.
Tweet: TweetID, Content, TweetLocation, NumberOfLikes, TimeStamp, etc.
UserFollowos: UserdID1, UserID2
FavoriteTweets: UserID, TweetID, TimeStamp
```

我们应该使用哪个数据库系统?像Cassandra这样的NoSQL是最适合我们的，还是我们应该使用类似mysql的解决方案。我们应该使用什么样的块存储来存储照片和视频?

### Step 5: 高级设计

用5-6个方框表示系统的核心组件绘制框图。您应该从端到端确定解决实际问题所需的足够的组件。

对于Twitter，在较高的层次上，我们需要多个应用服务器来为所有的读写请求提供服务，而负载均衡器在它们前面用于流量分配。如果我们假设我们将有更多的读流量(与写流量相比)，我们可以决定使用单独的服务器来处理这些场景。在后台，我们需要一个高效的数据库，它可以存储所有的tweets并支持大量的读取。我们还需要一个分布式文件存储系统来存储照片和视频。

### Step 6: 详细设计

深入挖掘2-3个组件;面试官的反馈应该总是引导你了解她希望你进一步解释的系统的哪些部分。你应该能够提供不同的方法，它们的优缺点，为什么你会选择其中一个?记住，没有单一的答案，唯一重要的事情是考虑不同选择之间的权衡，同时记住系统约束。

● 由于我们将存储大量的数据，我们应该如何划分我们的数据，以分发到多个数据库?我们是否应该将用户的所有数据存储在同一个数据库中?它会引起什么问题?

● 我们该如何处理那些经常发推或关注很多人的热门用户呢?

● 既然用户的时间线将包含最近的(和相关的)推文，我们应该尝试以一种优化的方式来存储我们的数据，以扫描最新的推文?

● 我们应该在多大程度上以及在哪一层引入缓存来提高速度?

● 哪些组件需要更好的负载均衡?

### Step 7: 识别并解决瓶颈

试着尽可能多地讨论瓶颈和缓解它们的不同方法。

● 我们的系统有任何单点故障吗?我们正在做些什么来减轻它?

● 我们是否有足够的数据副本，即使我们失去了几台服务器，我们仍然可以服务我们的用户?

● 类似地，我们是否有足够多的不同服务的副本正在运行，以便一些故障不会导致整个系统关闭?

● 我们如何监控服务的性能?当关键组件出现故障或性能下降时，我们是否会收到警报?

综上所述，准备和组织好面试是系统设计面试成功的关键。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://vagrant.gitbook.io/grokking-system-design/xi-tong-she-ji-yan-jin-zhi-nan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
