Skip to content

Commit 2c6e3bb

Browse files
committed
系统设计-在AWS上扩展到数百万用户的系统
1 parent 4f5c03c commit 2c6e3bb

File tree

2 files changed

+318
-0
lines changed

2 files changed

+318
-0
lines changed
Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
## 第一步 :弄清用例与约束
2+
3+
> 收集需求和问题的范围
4+
> 通过问问题来弄清用例与约束
5+
> 讨论假设
6+
7+
我们假定以下用例
8+
9+
### 用例
10+
解决这个问题需要采用迭代的方法:
11+
12+
1. 基准/负载测试
13+
2. 瓶颈检测
14+
3. 评估替代方案来解决瓶颈
15+
4. 重复以上
16+
17+
这是将基本设计升级为可扩展设计的良好模式
18+
19+
除非你有AWS的背景或者正在申请AWS的相关职位,否则在AWS上的实现细节不需要了解。然而**大部分在这里讨论的原理可以应用到除了AWS以外更通用的地方**
20+
21+
#### 我们将问题约束到如下范围
22+
* **用户**发送读或写请求
23+
* **服务**处理,存储用户数据然后返回结果
24+
* **服务**需要从少量用户发展到数百万用户
25+
* 在我们升级架构来处理大量用户请求时,讨论通用的扩展模式
26+
* **服务**需要高可用
27+
28+
### 约束和假设
29+
30+
#### 状态假设
31+
32+
* 流量分布不均
33+
* 需要关系型数据
34+
* 从单个用户扩展到千万级用户
35+
* 用户增加的标识:
36+
* 用户数+
37+
* 用户数++
38+
* 用户数+++
39+
* ...
40+
* 一千万用户
41+
* 每月10亿次写入
42+
* 每月1000亿次读取
43+
* 100:1读写比
44+
* 每次写入1KB内容
45+
46+
#### 计算方式
47+
48+
**如果你想做一个大致估算,请向你的面试官表明以下数据:**
49+
50+
* 每月1TB数据写入
51+
* 每次写入1KB数据 * 每月10亿次写入
52+
* 3年有3TB数据写入
53+
* 假设大多数写入是新的内容而不是已有内容的更新
54+
* 平均每秒400次写入
55+
* 平均每秒40000次读取
56+
57+
方便的转换公式:
58+
59+
* 每月有250万秒
60+
* 每秒一个请求 = 每月250万个请求
61+
* 每秒40个请求 = 每月1亿个请求
62+
* 每秒400个请求 = 每月10亿个请求
63+
64+
## 第二步:创建高层设计
65+
66+
> 大致写出包含所有重要组件的高层设计
67+
68+
![Imgur](http://i.imgur.com/B8LDKD7.png)
69+
70+
## 第三步:设计核心组件
71+
72+
> 深入每个核心组件的细节
73+
74+
### 用例:用户发送读或写的请求
75+
76+
#### 目标
77+
78+
* 对于仅仅的1-2个用户,你只需要一个基本的配置
79+
* 简单的单体应用
80+
* 当需要的时候垂直缩放
81+
* 监控来确定瓶颈
82+
83+
#### 从单体应用开始
84+
85+
* EC2上的**服务器**
86+
* 存储用户数据
87+
* [**MySQL数据库**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9Frdbms)
88+
89+
使用**垂直扩展**:
90+
91+
* 选择更好性能的机器
92+
* 密切关注监控指标以确定如何扩大规模
93+
* 使用基本监控来确定瓶颈:CPU,内存,IO,网络等
94+
* CloudWatch, top, nagios, statsd, graphite等
95+
* 垂直缩放可能会很昂贵
96+
* 没有故障转移措施
97+
98+
*替代方案和其他细节:*
99+
100+
* **垂直扩展**的替代是[**水平扩展**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E6%B0%B4%E5%B9%B3%E6%89%A9%E5%B1%95)
101+
102+
#### 从SQL开始,考虑NoSQL
103+
104+
约束里我们需要关系型数据。我们在开始的时候可以在单机上用**MySQL数据库**.
105+
106+
*替代方案和其他细节:*
107+
108+
* [关系型数据库](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9Frdbms)
109+
* 使用[SQL还是NoSQL](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#sql-%E8%BF%98%E6%98%AF-nosql)的原因
110+
111+
#### 分配公网静态IP
112+
113+
* 弹性IP提供一个重启之后不会更改的公网端口
114+
* 有效的帮助故障转移,只需要将域名指向新IP
115+
116+
#### 使用DNS
117+
118+
使用Route 53添加**DNS**将域名映射到实例的公共IP
119+
120+
*替代方案和其他细节:*
121+
122+
* [DNS](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%9F%9F%E5%90%8D%E7%B3%BB%E7%BB%9F)
123+
124+
#### 保护web服务器
125+
126+
* 开启必要的端口
127+
* 允许web服务器对于以下端口回复:
128+
* 80 - HTTP
129+
* 443 - HTTPS
130+
* 22 - SSH(白名单)
131+
* 阻止web服务器进行出站连接
132+
133+
*替代方案和其他细节:*
134+
135+
* [安全](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%AE%89%E5%85%A8)
136+
137+
## 第四步:扩展设计
138+
139+
> 鉴于约束条件,确定并解决瓶颈
140+
141+
### 用户数+
142+
143+
![Imgur](http://i.imgur.com/rrfjMXB.png)
144+
145+
#### 假设
146+
147+
我们的用户数正在增加并且在我们单体应用上的负载也在增加。我们的**基准/负载测试****瓶颈**指向了**MySQL数据库**占用更多内存和CPU资源,同时用户内容正在填满磁盘空间
148+
149+
到目前为止我们可以通过**水平扩展**解决问题。但不幸的是已经变得非常昂贵并且**MySQL数据库****web服务器**无法独立扩展
150+
151+
#### 目标
152+
153+
* 减轻单体应用的负载并且允许独立扩展
154+
* 将静态内容分开存储到**AWS对象存储**
155+
* 移动**MySQL数据库**到独立的服务上
156+
* 缺点
157+
* 这些改变将增加复杂度并且需要**Web服务器**指向**对象存储****MySQL数据库**
158+
* 新组件额外的安全措施
159+
* AWS的费用将会增加但应该与自己管理类似系统成本进行权衡
160+
161+
#### 分离存储静态内容
162+
163+
* 考虑使用S3作为**对象存储**
164+
* 高扩展和可靠性
165+
* 服务端加密
166+
* 移动静态内容到S3
167+
* 用户文件
168+
* JS
169+
* CSS
170+
* 图片
171+
* 视频
172+
173+
#### 移动MySQL数据库到独立的服务
174+
175+
* 考虑使用RDS服务管理**MySQL数据库**
176+
* 扩展和管理简单
177+
* 多个可用区
178+
* 静态加密
179+
180+
#### 保护系统
181+
182+
* 在传输和静止时加密数据
183+
* 使用虚拟私有网络
184+
* 为单个**Web服务器**创建公共子网以便可以发送和接收网上的流量
185+
* 为其他组件创建私有网络,组织外部访问
186+
* 每个组件仅仅对白名单IP开放端口
187+
188+
### 用户数++
189+
190+
![Imgur](http://i.imgur.com/raoFTXM.png)
191+
192+
#### 假设
193+
194+
我们的**基准/负载测试****瓶颈检测**表明我们的单体**Web服务器**在高峰期出现瓶颈,导致回应慢,在某些情况下宕机。随着服务的成熟,我们希望提高可用性和冗余度
195+
196+
#### 目的
197+
198+
* 以下目标尝试解决**Web服务器**的扩展问题
199+
* 基于**基准/负载测试****瓶颈检测**,你可能只需要实现这些技术中的一个或者两个
200+
* 使用[**水平扩展**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E6%B0%B4%E5%B9%B3%E6%89%A9%E5%B1%95)处理不断增加的负载并解决单体故障
201+
* 添加[**负载均衡器**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%99%A8)
202+
* ELB是高可用的
203+
* 如果你想配置自己的**负载均衡器**, 在多个可用区配置[主-主](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%8F%8C%E5%B7%A5%E4%BD%9C%E5%88%87%E6%8D%A2active-active)[主-备](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%B7%A5%E4%BD%9C%E5%88%B0%E5%A4%87%E7%94%A8%E5%88%87%E6%8D%A2active-passive)可以提高可用性
204+
* 在**负载均衡器**上关闭SSL去减少在后端服务器上的计算负载并简化证书管理
205+
* 使用多个**Web服务器**分布到多个区域
206+
* 使用多个[**主从故障切换**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6)模式的**MySQL**实例来增进冗余度
207+
***Web服务器**[**应用服务器**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%BA%94%E7%94%A8%E5%B1%82)分开
208+
* 独立扩展和配置这两层
209+
* **Web服务器**可以作为[**反向代理服务器**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86web-%E6%9C%8D%E5%8A%A1%E5%99%A8)
210+
* 比如你可以添加**应用服务器**处理**读API**而其他**应用服务器**处理**写API**
211+
* 移动静态(和一些动态)内容到[**CDN**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%86%85%E5%AE%B9%E5%88%86%E5%8F%91%E7%BD%91%E7%BB%9Ccdn)比如CloudFount去减少负载和延迟
212+
213+
### Users+++
214+
215+
![Imgur](http://i.imgur.com/OZCxJr0.png)
216+
217+
**注意:** 为了避免过于混乱,没有显示**内部负载均衡器**
218+
219+
#### 假设
220+
221+
我们的**基准/负载测试****瓶颈检测**表明我们的读请求很多(100:1读写比),我们的数据库因为大量读取请求导致性能不佳
222+
223+
#### 目标
224+
225+
* 以下目标尝试去解决在**MySQL数据库**上的问题
226+
* 基于**基准/负载测试****瓶颈检测**,你可能只需要实现这些技术中的一个或者两个
227+
* 移动以下数据到[**内存缓存**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E7%BC%93%E5%AD%98),比如Elasticache去减少负载和延迟:
228+
***MySQL**中经常读取的内容
229+
* 首先,在实现**内存缓存**之前试图配置**MySQL数据库**的缓存看是否足以解决瓶颈
230+
* 来自**Web服务器**的session数据
231+
* **Web服务器**变成无状态服务,允许**自动缩放**
232+
* 从内存读取1MB需要250微秒,而SSD需要4倍的时间,从硬盘读取需要80倍时间
233+
* 添加[**MySQL只读副本**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6)来减少主服务器的负载
234+
* 添加更多**Web服务器****应用服务器**来提升响应
235+
236+
#### 添加MySQL只读副本
237+
238+
* 除了增加和扩展**内存缓存**外, **MySQL只读副本**也能帮助减轻**MySQL主节点**的负载
239+
* 添加**Web服务器**的逻辑来分开读写数据
240+
***MySQL只读副本**前添加**负载均衡器**(图里没画)
241+
242+
### 用户数++++
243+
244+
![Imgur](http://i.imgur.com/3X8nmdL.png)
245+
246+
#### 假设
247+
248+
我们的**基准/负载测试****瓶颈检测**表明在正常工作时间内流量激增,在用户离开办公室时显著下降。我们认为我们可以根据实际负载自动调整服务器来降低成本。我们是个小公司,因此我们希望尽可能多地**自动缩放**
249+
250+
#### 目标
251+
252+
* 添加**自动缩放**来根据需求提供实例数量
253+
* 跟上流量的高峰
254+
* 通过关闭未使用的实例来减少费用
255+
* DevOps自动化
256+
* Chef, Puppet, Ansible等
257+
* 继续监控指标以解决瓶颈
258+
* **主机级别** - 查看单个EC2实例
259+
* **汇总级别** - 查看负载均衡器统计信息
260+
* **日志分析** - CloudWatch, CloudTrail, Loggly, Splunk, Sumo
261+
* **外部网站性能** - Pingdom或New Relic
262+
* **处理通知和时间** - PagerDuty
263+
* **错误报告** - Sentry
264+
265+
#### 添加自动缩放
266+
267+
* 考虑AWS的托管服务**自动缩放**
268+
* 为每个**Web服务器****应用服务器**创建一个组, 每个组放到多个可用区中
269+
* 设置最小和最大实例数
270+
* 通过CloudWatch触发向上和向下扩展
271+
* 一段时间内的指标:
272+
* CPU负载
273+
* 延迟
274+
* 网络流量
275+
* 自定义指标
276+
* 缺点
277+
* 自动缩放可能会带来复杂性
278+
* 系统可能需要一段时间才能适当扩展以满足不断增长的需求,或者在需求下降时缩小规模
279+
280+
### Users+++++
281+
282+
![Imgur](http://i.imgur.com/jj3A5N8.png)
283+
284+
**注意:** **自动缩放**组未在图中显示
285+
286+
#### 假设
287+
288+
随着服务继续朝着约束中的数字增长, **基准/负载测试****瓶颈检测**继续迭代来发现和解决新的瓶颈
289+
290+
#### 目标
291+
292+
由于问题的限制,我们将继续解决扩展问题:
293+
294+
* 如果我们的**MySQL数据库**开始变得非常大,我们可能会考虑只将有限时间段的数据存储在数据库中,同时将其余数据存储在Redshift等数据仓库中
295+
* 像Redshift这样的数据仓库可以轻松处理每月1TB的新内容
296+
* 每秒平均读取请求4万次,读取常用数据的流量可以通过扩展**内存缓存**来解决,这对于处理不均匀分布的流量和流量峰值也很有用
297+
* **SQL只读副本**可能在处理缓存未命中时遇到问题,我们可能需要采用其他SQL扩展模式
298+
* 对于单个**SQL写服务**来说,每秒400次平均写入次数(可能更高的峰值)可能很难,同时也表明需要额外的缩放技术
299+
300+
SQL扩展模式包括:
301+
302+
* [联合](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E8%81%94%E5%90%88)
303+
* [分片](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%88%86%E7%89%87)
304+
* [非规范化](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E9%9D%9E%E8%A7%84%E8%8C%83%E5%8C%96)
305+
* [SQL调优](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#sql-%E8%B0%83%E4%BC%98)
306+
307+
为了进一步解决高读取和写入请求,我们还应考虑将适当的数据移动到[**NoSQL数据库**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#nosql),例如DynamoDB
308+
309+
我们可以进一步分离[**应用服务器**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%BA%94%E7%94%A8%E5%B1%82)来允许独立的缩放。不需要实时完成的批处理和计算可以使用**队列****工作程序**[**异步**](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%BC%82%E6%AD%A5)完成:
310+
311+
* 例如,在照片服务中,照片上传和缩略图创建可以分开:
312+
* **客户端**上传图片
313+
* **应用程序服务器**放一个任务到**队列**
314+
* **工作服务****队列**中拉取到任务:
315+
* 创建缩略图
316+
* 上传到**数据库**
317+
* 存储缩略图到**对象存储**

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@
5252
### 系统设计
5353
* [从面试者角度设计一个系统设计题](http://www.wangtianyi.top/blog/2018/08/31/xi-tong-she-ji-mian-shi-ti-:zong-he-kao-cha-mian-shi-zhe-de-da-zhao/?utm_source=github&utm_medium=github)
5454
* [系统设计题答题套路](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md#%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86%E4%B8%80%E4%B8%AA%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1%E7%9A%84%E9%9D%A2%E8%AF%95%E9%A2%98)
55+
* [在AWS上扩展到数百万用户的系统](https://github.com/xbox1994/2018-Java-Interview/blob/master/MD/系统设计-在AWS上扩展到数百万用户的系统.md)
5556

5657
欢迎光临[91Code](http://www.91code.info/?utm_source=github&utm_medium=github),发现更多技术资源~

0 commit comments

Comments
 (0)