Update README.md

pull/374/head
lsvih 2017-09-27 20:20:59 +08:00 committed by GitHub
parent c7a8ae416f
commit 40913b65c4
1 changed files with 197 additions and 198 deletions

View File

@ -1,126 +1,126 @@
# Design the Twitter timeline and search # 设计推特时间轴与搜索功能
*Note: This document links directly to relevant areas found in the [system design topics](https://github.com/donnemartin/system-design-primer#index-of-system-design-topics) to avoid duplication. Refer to the linked content for general talking points, tradeoffs, and alternatives.* **注意:这个文档中的链接会直接指向[系统设计主题索引](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#系统设计主题的索引)中的有关部分,以避免重复的内容。你可以参考链接的相关内容,来了解其总的要点、方案的权衡取舍以及可选的替代方案。**
**Design the Facebook feed** and **Design Facebook search** are similar questions. **设计 Facebook 的 feed** 与**设计 Facebook 搜索**与此为同一类型问题。
## Step 1: Outline use cases and constraints ## 第一步:简述用例与约束条件
> Gather requirements and scope the problem. > 搜集需求与问题的范围。
> Ask questions to clarify use cases and constraints. > 提出问题来明确用例与约束条件。
> Discuss assumptions. > 讨论假设。
Without an interviewer to address clarifying questions, we'll define some use cases and constraints. 我们将在没有面试官明确说明问题的情况下,自己定义一些用例以及限制条件。
### Use cases ### 用例
#### We'll scope the problem to handle only the following use cases #### 我们将把问题限定在仅处理以下用例的范围中
* **User** posts a tweet * **用户**发布了一篇推特
* **Service** pushes tweets to followers, sending push notifications and emails * **服务**将推特推送给关注者,给他们发送消息通知与邮件
* **User** views the user timeline (activity from the user) * **用户**浏览用户时间轴(用户最近的活动)
* **User** views the home timeline (activity from people the user is following) * **用户**浏览主页时间轴(用户关注的人最近的活动)
* **User** searches keywords * **用户**搜索关键词
* **Service** has high availability * **服务**需要有高可用性
#### Out of scope #### 不在用例范围内的有
* **Service** pushes tweets to the Twitter Firehose and other streams * **服务**向 Firehose 与其它流数据接口推送推特
* **Service** strips out tweets based on user's visibility settings * **服务**根据用户的”是否可见“选项排除推特
* Hide @reply if the user is not also following the person being replied to * 隐藏未关注者的 @回复
* Respect 'hide retweets' setting * 关心”隐藏转发“设置
* Analytics * 数据分析
### Constraints and assumptions ### 限制条件与假设
#### State assumptions #### 提出假设
General 普遍情况
* Traffic is not evenly distributed * 网络流量不是均匀分布的
* Posting a tweet should be fast * 发布推特的速度需要足够快速
* Fanning out a tweet to all of your followers should be fast, unless you have millions of followers * 除非有上百万的关注者,否则将推特推送给粉丝的速度要足够快
* 100 million active users * 1 亿个活跃用户
* 500 million tweets per day or 15 billion tweets per month * 每天新发布 5 亿条推特,每月新发布 150 亿条推特
* Each tweet averages a fanout of 10 deliveries * 平均每条推特需要推送给 5 个人
* 5 billion total tweets delivered on fanout per day * 每天需要进行 50 亿次推送
* 150 billion tweets delivered on fanout per month * 每月需要进行 1500 亿次推送
* 250 billion read requests per month * 每月需要处理 2500 亿次读取请求
* 10 billion searches per month * 每月需要处理 100 亿次搜索
Timeline 时间轴功能
* Viewing the timeline should be fast * 浏览时间轴需要足够快
* Twitter is more read heavy than write heavy * 推特的读取负载要大于写入负载
* Optimize for fast reads of tweets * 需要为推特的快速读取进行优化
* Ingesting tweets is write heavy * 存入推特是高写入负载功能
Search 搜索功能
* Searching should be fast * 搜索速度需要足够快
* Search is read-heavy * 搜索是高负载读取功能
#### Calculate usage #### 计算用量
**Clarify with your interviewer if you should run back-of-the-envelope usage calculations.** **如果你需要进行粗略的用量计算,请向你的面试官说明。**
* Size per tweet: * 每条推特的大小:
* `tweet_id` - 8 bytes * `tweet_id` - 8 字节
* `user_id` - 32 bytes * `user_id` - 32 字节
* `text` - 140 bytes * `text` - 140 字节
* `media` - 10 KB average * `media` - 平均 10 KB
* Total: ~10 KB * 总计: 大约 10 KB
* 150 TB of new tweet content per month * 每月产生新推特的内容为 150 TB
* 10 KB per tweet * 500 million tweets per day * 30 days per month * 每条推特 10 KB * 每天 5 亿条推特 * 每月 30 天
* 5.4 PB of new tweet content in 3 years * 3 年产生新推特的内容为 5.4 PB
* 100 thousand read requests per second * 每秒需要处理 10 万次读取请求
* 250 billion read requests per month * (400 requests per second / 1 billion requests per month) * 每个月需要处理 2500 亿次请求 * (每秒 400 次请求 / 每月 10 亿次请求)
* 6,000 tweets per second * 每秒发布 6000 条推特
* 15 billion tweets delivered on fanout per month * (400 requests per second / 1 billion requests per month) * 每月发布 150 亿条推特 * (每秒 400 次请求 / 每月 10 次请求)
* 60 thousand tweets delivered on fanout per second * 每秒推送 6 万条推特
* 150 billion tweets delivered on fanout per month * (400 requests per second / 1 billion requests per month) * 每月推送 1500 亿条推特 * (每秒 400 次请求 / 每月 10 亿次请求)
* 4,000 search requests per second * 每秒 4000 次搜索请求
Handy conversion guide: 便利换算指南:
* 2.5 million seconds per month * 每个月有 250 万秒
* 1 request per second = 2.5 million requests per month * 每秒一个请求 = 每个月 250 万次请求
* 40 requests per second = 100 million requests per month * 每秒 40 个请求 = 每个月 1 亿次请求
* 400 requests per second = 1 billion requests per month * 每秒 400 个请求 = 每个月 10 亿次请求
## Step 2: Create a high level design ## 第二步:概要设计
> Outline a high level design with all important components. > 列出所有重要组件以规划概要设计。
![Imgur](http://i.imgur.com/48tEA2j.png) ![Imgur](http://i.imgur.com/48tEA2j.png)
## Step 3: Design core components ## 第三步:设计核心组件
> Dive into details for each core component. > 深入每个核心组件的细节。
### Use case: User posts a tweet ### 用例:用户发表了一篇推特
We could store the user's own tweets to populate the user timeline (activity from the user) in a [relational database](https://github.com/donnemartin/system-design-primer#relational-database-management-system-rdbms). We should discuss the [use cases and tradeoffs between choosing SQL or NoSQL](https://github.com/donnemartin/system-design-primer#sql-or-nosql). 我们可以将用户自己发表的推特存储在[关系数据库](https://github.com/donnemartin/system-design-primer#relational-database-management-system-rdbms)中。我们也可以讨论一下[究竟是用 SQL 还是用 NoSQL](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#sql-还是-nosql)。
Delivering tweets and building the home timeline (activity from people the user is following) is trickier. Fanning out tweets to all followers (60 thousand tweets delivered on fanout per second) will overload a traditional [relational database](https://github.com/donnemartin/system-design-primer#relational-database-management-system-rdbms). We'll probably want to choose a data store with fast writes such as a **NoSQL database** or **Memory Cache**. Reading 1 MB sequentially from memory takes about 250 microseconds, while reading from SSD takes 4x and from disk takes 80x longer.<sup><a href=https://github.com/donnemartin/system-design-primer#latency-numbers-every-programmer-should-know>1</a></sup> 构建用户主页时间轴(查看关注用户的活动)以及推送推特是件麻烦事。将特推传播给所有关注者(每秒约递送 6 万条推特)这一操作有可能会使传统的[关系数据库](https://github.com/donnemartin/system-design-primer#relational-database-management-system-rdbms)超负载。因此,我们可以使用 **NoSQL 数据库**或**内存数据库**之类的更快的数据存储方式。从内存读取 1 MB 连续数据大约要花 250 微秒,而从 SSD 读取同样大小的数据要花费 4 倍的时间,从机械硬盘读取需要花费 80 倍以上的时间。<sup><a href=https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#每个程序员都应该知道的延迟数>1</a></sup>
We could store media such as photos or videos on an **Object Store**. 我们可以将照片、视频之类的媒体存储于**对象存储**中。
* The **Client** posts a tweet to the **Web Server**, running as a [reverse proxy](https://github.com/donnemartin/system-design-primer#reverse-proxy-web-server) * **客户端**向应用[反向代理](https://github.com/donnemartin/system-design-primer#reverse-proxy-web-server)的**Web 服务器**发送一条推特
* The **Web Server** forwards the request to the **Write API** server * **Web 服务器**将请求转发给**写 API**服务器
* The **Write API** stores the tweet in the user's timeline on a **SQL database** * **写 API**服务器将推特使用 **SQL 数据库**存储于用户时间轴中
* The **Write API** contacts the **Fan Out Service**, which does the following: * **写 API**调用**消息输出服务**,进行以下操作:
* Queries the **User Graph Service** to find the user's followers stored in the **Memory Cache** * 查询**用户 图 服务**找到存储于**内存缓存**中的此用户的粉丝
* Stores the tweet in the *home timeline of the user's followers* in a **Memory Cache** * 将推特存储于**内存缓存**中的**此用户的粉丝的主页时间轴**中
* O(n) operation: 1,000 followers = 1,000 lookups and inserts * O(n) 复杂度操作: 1000 名粉丝 = 1000 次查找与插入
* Stores the tweet in the **Search Index Service** to enable fast searching * 将特推存储在**搜索索引服务**中,以加快搜索
* Stores media in the **Object Store** * 将媒体存储于**对象存储**中
* Uses the **Notification Service** to send out push notifications to followers: * 使用**通知服务**向粉丝发送推送:
* Uses a **Queue** (not pictured) to asynchronously send out notifications * 使用**队列**异步推送通知
**Clarify with your interviewer how much code you are expected to write**. **向你的面试官告知你准备写多少代码**。
If our **Memory Cache** is Redis, we could use a native Redis list with the following structure: 如果我们用 Redis 作为**内存缓存**,那可以用 Redis 原生的 list 作为其数据结构。结构如下:
``` ```
tweet n+2 tweet n+1 tweet n tweet n+2 tweet n+1 tweet n
@ -128,9 +128,9 @@ If our **Memory Cache** is Redis, we could use a native Redis list with the foll
| tweet_id user_id meta | tweet_id user_id meta | tweet_id user_id meta | | tweet_id user_id meta | tweet_id user_id meta | tweet_id user_id meta |
``` ```
The new tweet would be placed in the **Memory Cache**, which populates user's home timeline (activity from people the user is following). 新发布的推特将被存储在对应用户(关注且活跃的用户)的主页时间轴的**内存缓存**中。
We'll use a public [**REST API**](https://github.com/donnemartin/system-design-primer#representational-state-transfer-rest): 我们可以调用一个公共的 [REST API](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#表述性状态转移rest)
``` ```
$ curl -X POST --data '{ "user_id": "123", "auth_token": "ABC123", \ $ curl -X POST --data '{ "user_id": "123", "auth_token": "ABC123", \
@ -138,7 +138,7 @@ $ curl -X POST --data '{ "user_id": "123", "auth_token": "ABC123", \
https://twitter.com/api/v1/tweet https://twitter.com/api/v1/tweet
``` ```
Response: 返回:
``` ```
{ {
@ -150,24 +150,24 @@ Response:
} }
``` ```
For internal communications, we could use [Remote Procedure Calls](https://github.com/donnemartin/system-design-primer#remote-procedure-call-rpc). 而对于服务器内部的通信,我们可以使用 [RPC](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#远程过程调用协议rpc)。
### Use case: User views the home timeline ### 用例:用户浏览主页时间轴
* The **Client** posts a home timeline request to the **Web Server** * **客户端**向 **Web 服务器**发起一次读取主页时间轴的请求
* The **Web Server** forwards the request to the **Read API** server * **Web 服务器**将请求转发给**读取 API**服务器
* The **Read API** server contacts the **Timeline Service**, which does the following: * **读取 API**服务器调用**时间轴服务**进行以下操作:
* Gets the timeline data stored in the **Memory Cache**, containing tweet ids and user ids - O(1) * 从**内存缓存**读取时间轴数据,其中包括推特 id 与用户 id - O(1)
* Queries the **Tweet Info Service** with a [multiget](http://redis.io/commands/mget) to obtain additional info about the tweet ids - O(n) * 通过 [multiget](http://redis.io/commands/mget) 向**推特信息服务**进行查询,以获取相关 id 推特的额外信息 - O(n)
* Queries the **User Info Service** with a multiget to obtain additional info about the user ids - O(n) * 通过 muiltiget 向**用户信息服务**进行查询,以获取相关 id 用户的额外信息 - O(n)
REST API: REST API
``` ```
$ curl https://twitter.com/api/v1/home_timeline?user_id=123 $ curl https://twitter.com/api/v1/home_timeline?user_id=123
``` ```
Response: 返回:
``` ```
{ {
@ -187,146 +187,145 @@ Response:
}, },
``` ```
### Use case: User views the user timeline ### 用例:用户浏览用户时间轴
* The **Client** posts a home timeline request to the **Web Server** * **客户端**向**Web 服务器**发起获得主页时间轴的请求
* The **Web Server** forwards the request to the **Read API** server * **Web 服务器**将请求转发给**读取 API**服务器
* The **Read API** retrieves the user timeline from the **SQL Database** * **读取 API**从 **SQL 数据库**中取出用户的时间轴
The REST API would be similar to the home timeline, except all tweets would come from the user as opposed to the people the user is following. REST API 与前面的主页时间轴类似,区别只在于取出的推特是由用户自己发送而不是关注人发送。
### Use case: User searches keywords ### 用例:用户搜索关键词
* The **Client** sends a search request to the **Web Server** * **客户端**将搜索请求发给**Web 服务器**
* The **Web Server** forwards the request to the **Search API** server * **Web 服务器**将请求转发给**搜索 API**服务器
* The **Search API** contacts the **Search Service**, which does the following: * **搜索 API**调用**搜索服务**进行以下操作:
* Parses/tokenizes the input query, determining what needs to be searched * 对输入进行转换与分词,弄明白需要搜索什么东西
* Removes markup * 移除标点等额外内容
* Breaks up the text into terms * 将文本打散为词组
* Fixes typos * 修正拼写错误
* Normalizes capitalization * 规范字母大小写
* Converts the query to use boolean operations * 将查询转换为布尔操作
* Queries the **Search Cluster** (ie [Lucene](https://lucene.apache.org/)) for the results: * 查询**搜索集群**(例如[Lucene](https://lucene.apache.org/))检索结果:
* [Scatter gathers](https://github.com/donnemartin/system-design-primer#under-development) each server in the cluster to determine if there are any results for the query * 对集群内的所有服务器进行查询,将有结果的查询进行[发散聚合Scatter gathers](https://github.com/donnemartin/system-design-primer#under-development)
* Merges, ranks, sorts, and returns the results * 合并取到的条目,进行评分与排序,最终返回结果
REST API: REST API
``` ```
$ curl https://twitter.com/api/v1/search?query=hello+world $ curl https://twitter.com/api/v1/search?query=hello+world
``` ```
The response would be similar to that of the home timeline, except for tweets matching the given query. 返回结果与前面的主页时间轴类似,只不过返回的是符合查询条件的推特。
## Step 4: Scale the design ## 第四步:架构扩展
> Identify and address bottlenecks, given the constraints. > 根据限制条件,找到并解决瓶颈。
![Imgur](http://i.imgur.com/jrUBAF7.png) ![Imgur](http://i.imgur.com/MzExP06.png)
**Important: Do not simply jump right into the final design from the initial design!** **重要提示:不要从最初设计直接跳到最终设计中!**
State you would 1) **Benchmark/Load Test**, 2) **Profile** for bottlenecks 3) address bottlenecks while evaluating alternatives and trade-offs, and 4) repeat. See [Design a system that scales to millions of users on AWS](../scaling_aws/README.md) as a sample on how to iteratively scale the initial design. 现在你要 1) **基准测试、负载测试**。2) **分析、描述**性能瓶颈。3) 在解决瓶颈问题的同时评估替代方案、权衡利弊。4) 重复以上步骤。请阅读[「设计一个系统,并将其扩大到为数以百万计的 AWS 用户服务」](../scaling_aws/README.md) 来了解如何逐步扩大初始设计。
It's important to discuss what bottlenecks you might encounter with the initial design and how you might address each of them. For example, what issues are addressed by adding a **Load Balancer** with multiple **Web Servers**? **CDN**? **Master-Slave Replicas**? What are the alternatives and **Trade-Offs** for each? 讨论初始设计可能遇到的瓶颈及相关解决方案是很重要的。例如加上一个配置多台 **Web 服务器**的**负载均衡器**是否能够解决问题?**CDN**呢?**主从复制**呢?它们各自的替代方案和需要**权衡**的利弊又有什么呢?
We'll introduce some components to complete the design and to address scalability issues. Internal load balancers are not shown to reduce clutter. 我们将会介绍一些组件来完成设计,并解决架构扩张问题。内置的负载均衡器将不做讨论以节省篇幅。
*To avoid repeating discussions*, refer to the following [system design topics](https://github.com/donnemartin/system-design-primer#index-of-system-design-topics) for main talking points, tradeoffs, and alternatives: **为了避免重复讨论**,请参考[系统设计主题索引](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#系统设计主题的索引)相关部分来了解其要点、方案的权衡取舍以及可选的替代方案。
* [DNS](https://github.com/donnemartin/system-design-primer#domain-name-system) * [DNS](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#域名系统)
* [CDN](https://github.com/donnemartin/system-design-primer#content-delivery-network) * [负载均衡器](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#负载均衡器)
* [Load balancer](https://github.com/donnemartin/system-design-primer#load-balancer) * [水平拓展](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#水平扩展)
* [Horizontal scaling](https://github.com/donnemartin/system-design-primer#horizontal-scaling) * [反向代理web 服务器)](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#反向代理web-服务器)
* [Web server (reverse proxy)](https://github.com/donnemartin/system-design-primer#reverse-proxy-web-server) * [API 服务(应用层)](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#应用层)
* [API server (application layer)](https://github.com/donnemartin/system-design-primer#application-layer) * [缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#缓存)
* [Cache](https://github.com/donnemartin/system-design-primer#cache) * [关系型数据库管理系统 (RDBMS)](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#关系型数据库管理系统rdbms)
* [Relational database management system (RDBMS)](https://github.com/donnemartin/system-design-primer#relational-database-management-system-rdbms) * [SQL 故障主从切换](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#故障切换)
* [SQL write master-slave failover](https://github.com/donnemartin/system-design-primer#fail-over) * [主从复制](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#主从复制)
* [Master-slave replication](https://github.com/donnemartin/system-design-primer#master-slave-replication) * [一致性模式](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#一致性模式)
* [Consistency patterns](https://github.com/donnemartin/system-design-primer#consistency-patterns) * [可用性模式](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#可用性模式)
* [Availability patterns](https://github.com/donnemartin/system-design-primer#availability-patterns)
The **Fanout Service** is a potential bottleneck. Twitter users with millions of followers could take several minutes to have their tweets go through the fanout process. This could lead to race conditions with @replies to the tweet, which we could mitigate by re-ordering the tweets at serve time. **消息输出服务**有可能成为性能瓶颈。那些有着百万数量关注着的用户可能发一条推特就需要好几分钟才能完成消息输出进程。这有可能使 @回复 这种推特时出现竞争条件,因此需要根据服务时间对此推特进行重排序来降低影响。
We could also avoid fanning out tweets from highly-followed users. Instead, we could search to find tweets for high-followed users, merge the search results with the user's home timeline results, then re-order the tweets at serve time. 我们还可以避免从高关注量的用户输出推特。相反,我们可以通过搜索来找到高关注量用户的推特,并将搜索结果与用户的主页时间轴合并,再根据时间对其进行排序。
Additional optimizations include: 此外,还可以通过以下内容进行优化:
* Keep only several hundred tweets for each home timeline in the **Memory Cache** * 仅为每个主页时间轴在**内存缓存**中存储数百条推特
* Keep only active users' home timeline info in the **Memory Cache** * 仅在**内存缓存**中存储活动用户的主页时间轴
* If a user was not previously active in the past 30 days, we could rebuild the timeline from the **SQL Database** * 如果某个用户在过去 30 天都没有产生活动,那我们可以使用 **SQL 数据库**重新构建他的时间轴
* Query the **User Graph Service** to determine who the user is following * 使用**用户 图 服务**来查询并确定用户关注的人
* Get the tweets from the **SQL Database** and add them to the **Memory Cache** * 从 **SQL 数据库**中取出推特,并将它们存入**内存缓存**
* Store only a month of tweets in the **Tweet Info Service** * 仅在**推特信息服务**中存储一个月的推特
* Store only active users in the **User Info Service** * 仅在**用户信息服务**中存储活动用户的信息
* The **Search Cluster** would likely need to keep the tweets in memory to keep latency low * **搜索集群**需要将推特保留在内存中,以降低延迟
We'll also want to address the bottleneck with the **SQL Database**. 我们还可以考虑优化 **SQL 数据库** 来解决一些瓶颈问题。
Although the **Memory Cache** should reduce the load on the database, it is unlikely the **SQL Read Replicas** alone would be enough to handle the cache misses. We'll probably need to employ additional SQL scaling patterns. **内存缓存**能减小一些数据库的负载,靠 **SQL Read 副本**已经足够处理缓存未命中情况。我们还可以考虑使用一些额外的 SQL 性能拓展技术。
The high volume of writes would overwhelm a single **SQL Write Master-Slave**, also pointing to a need for additional scaling techniques. 高容量的写入将淹没单个的 **SQL 写主从**模式,因此需要更多的拓展技术。
* [Federation](https://github.com/donnemartin/system-design-primer#federation) * [联合](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#联合)
* [Sharding](https://github.com/donnemartin/system-design-primer#sharding) * [分片](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#分片)
* [Denormalization](https://github.com/donnemartin/system-design-primer#denormalization) * [非规范化](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#非规范化)
* [SQL Tuning](https://github.com/donnemartin/system-design-primer#sql-tuning) * [SQL 调优](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#sql-调优)
We should also consider moving some data to a **NoSQL Database**. 我们也可以考虑将一些数据移至 **NoSQL 数据库**
## Additional talking points ## 其它要点
> Additional topics to dive into, depending on the problem scope and time remaining. > 是否深入这些额外的主题,取决于你的问题范围和剩下的时间。
#### NoSQL #### NoSQL
* [Key-value store](https://github.com/donnemartin/system-design-primer#key-value-store) * [键-值存储](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#键-值存储)
* [Document store](https://github.com/donnemartin/system-design-primer#document-store) * [文档类型存储](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#文档类型存储)
* [Wide column store](https://github.com/donnemartin/system-design-primer#wide-column-store) * [列型存储](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#列型存储)
* [Graph database](https://github.com/donnemartin/system-design-primer#graph-database) * [图数据库](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#图数据库)
* [SQL vs NoSQL](https://github.com/donnemartin/system-design-primer#sql-or-nosql) * [SQL vs NoSQL](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#sql-还是-nosql)
### Caching ### 缓存
* Where to cache * 在哪缓存
* [Client caching](https://github.com/donnemartin/system-design-primer#client-caching) * [客户端缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#客户端缓存)
* [CDN caching](https://github.com/donnemartin/system-design-primer#cdn-caching) * [CDN 缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#cdn-缓存)
* [Web server caching](https://github.com/donnemartin/system-design-primer#web-server-caching) * [Web 服务器缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#web-服务器缓存)
* [Database caching](https://github.com/donnemartin/system-design-primer#database-caching) * [数据库缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#数据库缓存)
* [Application caching](https://github.com/donnemartin/system-design-primer#application-caching) * [应用缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#应用缓存)
* What to cache * 什么需要缓存
* [Caching at the database query level](https://github.com/donnemartin/system-design-primer#caching-at-the-database-query-level) * [数据库查询级别的缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#数据库查询级别的缓存)
* [Caching at the object level](https://github.com/donnemartin/system-design-primer#caching-at-the-object-level) * [对象级别的缓存](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#对象级别的缓存)
* When to update the cache * 何时更新缓存
* [Cache-aside](https://github.com/donnemartin/system-design-primer#cache-aside) * [缓存模式](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#缓存模式)
* [Write-through](https://github.com/donnemartin/system-design-primer#write-through) * [直写模式](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#直写模式)
* [Write-behind (write-back)](https://github.com/donnemartin/system-design-primer#write-behind-write-back) * [回写模式](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#回写模式)
* [Refresh ahead](https://github.com/donnemartin/system-design-primer#refresh-ahead) * [刷新](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#刷新)
### Asynchronism and microservices ### 异步与微服务
* [Message queues](https://github.com/donnemartin/system-design-primer#message-queues) * [消息队列](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#消息队列)
* [Task queues](https://github.com/donnemartin/system-design-primer#task-queues) * [任务队列](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#任务队列)
* [Back pressure](https://github.com/donnemartin/system-design-primer#back-pressure) * [背压](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#背压)
* [Microservices](https://github.com/donnemartin/system-design-primer#microservices) * [微服务](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#微服务)
### Communications ### 通信
* Discuss tradeoffs: * 可权衡选择的方案:
* External communication with clients - [HTTP APIs following REST](https://github.com/donnemartin/system-design-primer#representational-state-transfer-rest) * 与客户端的外部通信 - [使用 REST 作为 HTTP API](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#表述性状态转移rest)
* Internal communications - [RPC](https://github.com/donnemartin/system-design-primer#remote-procedure-call-rpc) * 服务器内部通信 - [RPC](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#远程过程调用协议rpc)
* [Service discovery](https://github.com/donnemartin/system-design-primer#service-discovery) * [服务发现](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#服务发现)
### Security ### 安全性
Refer to the [security section](https://github.com/donnemartin/system-design-primer#security). 请参阅[「安全」](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#安全)一章。
### Latency numbers ### 延迟数值
See [Latency numbers every programmer should know](https://github.com/donnemartin/system-design-primer#latency-numbers-every-programmer-should-know). 请参阅[「每个程序员都应该知道的延迟数」](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#每个程序员都应该知道的延迟数)。
### Ongoing ### 持续探讨
* Continue benchmarking and monitoring your system to address bottlenecks as they come up * 持续进行基准测试并监控你的系统,以解决他们提出的瓶颈问题。
* Scaling is an iterative process * 架构拓展是一个迭代的过程。