
首先什么是系统设计?
The process of defining the architecture, components, modules, interfaces, and data for a system to satisfy specified requirements.
系统设计有四大要素。 第一,是要满足一个需求即Requirements;第二,对内容进行一个定义;第三,从不同维度去考虑宏观的架构层、组件层、模块层;第四,也要考虑到互相间交流的接口和相关传递的数据。所以这些内容一起构成了整个系统设计。
系统设计有什么层次呢? 从上向下是从概念层到逻辑层再到物理层,从清晰度来看,会从不清晰,到越来越清晰,到最清晰,角度则是从宏观到微观。换句话理解,如果系统设计时,我们从顶层向下做设计,那就是一个自上而下的方法;如果是自下层往顶层设计,就是一个自下而上的方法。在后文中我们分别称之为宏观设计与微观设计。我们以Netflix为例来讲这两个方法。

如何设计Netflix
现在我们通过设计Netflix,来具体了解什么是系统设计的SNAKE原则。

这是Netflix的官方网页,上面有各种用户信息、搜索功能、以及列出的各个频道:Netflix流行的电影(Popular on Netflix)、当前的趋势(Trending Now)、惊险刺激电影(Exciting Movies)、漫画动画(Goofy Comedies)等等。每个电影类目下面会有很多具体的电影,如果点击可以看到详细内容,相信大家十分熟悉。
宏观设计
Scenario(场景):用例/接口
第一步:枚举在Netflix里面,到底有哪些场景
第二步:选出里面最重要的排序
基本需求:播放电影
获得频道
获得频道内电影
播放频道内电影
这是三个基本需求的排序。
Necessary(限制):查看需求/假设
第一步:询问
第二步:预测
- 通过日活用户,计算平均并发用户
=日活用户/每日秒数*平均在线时长(假设为30min)
= 5,000,000 / (24 * 60 * 60) * (30 * 60)
= 104,167
- 高峰并发用户,通常是平均用户的2-10倍,这里假设为6倍
高峰并发用户 = 平均并发用户 * 6 = 625,000
- 假设未来3个月,Netflix用户涨2倍
- 3月后高峰并发用户 = 高峰并发用户 * 2 = 1,250,000
* *流量*
* - 单用户流量 = 3mbps(假设数据,满足看电影基本需求)
* - 3月后高峰流量 = 1,250,000 * 3 mbps = 3.75 Tb/s
* *内存*
- 单用户内存 = 10KB(假设用户数据不清空)
3月后高峰内存 = 5,000,000 * 2 * 10 KB= 100GB(当前日活用户500万,3个月后日活用户为2倍)
硬盘
- 电影数=14,000份,每部电影=50G(假设数据,且每部电影需要存储不同清晰度版本)
- 总硬盘=电影数单电影空间=14,00050GB=700TB
Application(应用):服务/算法
具体来看,我们有用户服务、频道服务和电影服务三种需求,在上面有一个接待员可以获得各种服务请求,接待员把所有服务接受完以后发送给后台的服务,就可以满足需求。

Kilobit(数据)
第一步:为每个请求添加服务模块
第二步:选择存储方式。对于用户数据用MySQL;频道数据用MongoDB;电影服务由于只是从文件出来,所以往往采取Movies的方式。

Evolve(进化)
第一步:分析
三个方向
更好:限制性条件,10个用户变为100个
更广:场景,是否还有支付场景等
更深:细节,是否用CDN,如何部署
三个角度
性能:单个点的计算能力如何,或某个算法的性能如何
扩展:如果机器或者用户量翻倍怎么办
鲁棒:发生各种危险,崩溃时服务器能不能处理
第二步:根据场景回溯并进化
以上是我们SNAKE五步原则在宏观设计中的应用。
微观设计
因为Netflix里推荐电影是最基本的一个需求,那我们就做一个具体的微观设计模块——推荐模块
如何设计推荐模块?
[image:31D5BBBD-90C1-46A7-83FF-770ECDF000DB-18349-00003D57A76D6211/46EF94A2-E9B2-4202-80F2-FCA3D3A6B0F1.png]
我们可以看到用户1和用户2重复喜欢的电影数有3个:m3、m5、m7。
我们的需求是:寻找一个用户的最相似用户。
Scenario(场景)
[image:380CD6F7-214C-4F59-BDAC-A58B8307980F-18349-00003D59219C3908/33B15465-DA6E-42B6-B1FF-E6C43C3CBFFF.png]
我们可以定义一个接口,定义之后直接找到我最相似的用户,输入一个用户ID,输出一个用户ID,接口就出来了。
Necessary(限制)
在微观设计里我们可以继续做预测,比如针对这个请求,它的QPS即每秒请求量是多少?
[image:CFBBE35B-6C6D-47B2-B0A9-5B28334709AC-18349-00003D5ABD820D5D/EAEC4D4C-2F47-4849-ACD7-EFEE87AC5101.png]
Algorithm(算法)&Kilobit(数据)
算法和数据在微观设计里往往可以放到一起。具体做时,不同的算法和不同的数据结构性能差异很大。
比如有3个用户u1,u2,u3,最简单的方法是两两比较。想算出与u1最相似的用户,就先把u1、u2比,发现相似度是1;u1、u3比,发现相似度是2。最终我们发现,这个算法的性能非常差,可能每一个计算都需要200毫秒,相当于每个计算节点只能计算5个QPS,而我们需要2000多QPS,明显无法达到。
[image:6506D45F-90F3-465D-8D5A-0BE95D72D5AC-18349-00003D5CE1C444B1/4AC1E2CF-B647-43CB-AFDD-8122AB3989B5.png]
Evolve(进化)
我们先看一下当前的架构:原始数据给推荐模块,推荐模块返回请求。
[image:B1DDDB7E-FBA0-4051-95CD-D4E4E35083BD-18349-00003D5E7BC647B2/D4119C6C-32B7-46BE-8719-286C8344BFFE.png]
因此我们需要从性能、扩展、鲁棒三个维度来进化。
1. 提升性能
怎么提升性能?提升单点的计算能力?
我们通过建立倒排索引,能够非常简单地优化算法的性能。比如现在把由用户建立改为由电影建立,即先计算出每个电影被哪些用户喜欢。比如m3被用户1、2、3喜欢。我们先找u1喜欢的电影,这里是m1、m3、m7,然后轮流遍历这些电影,每当这个电影还被其他用户喜欢,则相似度+1。于是我们就可以降低n的复杂度,计算所有的相似度。这样复杂度就从n的三次方降为了n的平方。所以性能大大提升,变成了每个20毫秒,能实现单机50QPS,但仍然无法达到需要的2000+QPS。
[image:52D38FB3-1AC2-41E4-B3C4-43C222EB23BF-18349-00003D615DC545A3/3C6C80AB-74BD-40A8-92A4-7581CB75C7A4.png]
这时的架构已经做了提升:通过加入一个准备器,将原始数据输入进来,并且创建索引返回给推荐器。
[image:BA00E10D-18EE-43EB-88F8-03A22DF3A0BB-18349-00003D6308699FB7/4986DC9F-D5BB-41F8-A6E0-031BE0709349.png]
2. 提升扩展性
之前有了一个简单的架构,能计算出所有索引,现在需要将推荐模块全部平行地放进来。现在不仅有一个推荐模块,还可以有好几个推荐模块,同时上面还有一个分配器,把整个推荐模块的请求分配给不同推荐器来进行计算。
[image:320CC916-AE69-43F0-9A53-E9341637317B-18349-00003D65221072D7/9BFD0854-7C09-4F51-82CF-3370785AD744.png]
那么问题是:需要多少个推荐器来满足2083QPS呢?
其实很简单,因为刚才单个推荐模块能满足50QPS,所以用2083除以50就可以得出答案,当然也可以多算几个来进行缓冲。
3. 提高鲁棒性
提高鲁棒性,防止服务器崩溃,需要怎么办呢?答案是做热备。
之前的数据有1个人管理,推荐器有一个模块在运行,上面是管理者在管理。
现在可以热备出另外一个数据集,把它们放一起;同时也热备出一个推荐模块放在一起。下图中每个橙色的虚框表示一个集群组合在一起。顶层可以用Apache接外部服务器顶住请求。还会有一些记录日志,比如Big Brother。它们中间通过一个消息分配者把消息分配出去。
如果要给系统进行升级,我们可以通过添加模块来轻松地实现。比如想加入一个Feed流,相当于新浪微博这样的架构,那只需要把这个模块添加到系统中。
[image:D0A434A5-4272-41AE-A3DF-42A409E16763-18349-00003D675BED419B/2AE5AFC8-6C0C-4FEF-9849-EF96568249A9.png]
上图可以看到,绿色的虚线表示它们之间进行消息传递;而绿色粗线表示它们之间有一个数据的快速通道,这样就不用所有消息都通过中间的消息传递者传输,避免影响效率。
总结:SNAKE原则
Scenario(场景)
Necessary(限制)
Application(应用)
Kilobit(数据)
Evolve(进化)
通过项目的搭建,建立Solid的系统设计思维,真正了解系统设计中会遇到的问题,并亲手解决这些问题,提升50%你的学习效率。
欢迎了解BitTiger大数据工程师、全栈工程师、大数据工程师直通车
BitTiger直通车特色
三个月、三个工业级别大项目
全面提升编程实力与简历背景
硅谷一线IT公司导师、了解痛点的助教
全方位指导及答疑
修改简历、模拟面试、职业咨询
Career Service全程护航
独家面试题库精讲
上百小时基础及面试视频资源助
点击“阅读原文”查看BitTiger直通车