Design Netflix

http://highscalability.com/blog/2017/12/11/netflix-what-happens-when-you-press-play.html?currentPage=2

Netflix 作为最大的电影电视剧串流平台,大家对旗下电视剧如纸牌屋和怪奇物语也是耳熟能详。它占据了互联网下载流量的12.9%,超过 Youtube 接近一倍。大家有没有好奇 Netflix 是如何支持如此巨大的下载流量的呢?今天我们就来为你揭开它的神秘面纱。

Netflix 相似的串流平台有 Amazon Prime Video, Hulu, Youtube 等等。在这些服务的系统设计中也可以参考本文。

1. 理解需求

1.1 商业目的

让世界范围内的巨量用户可以在线看电影电视剧。

1.2 功能性需求

  • 用户可以顺畅地在线看视频

  • 视频发行方可以上传视频

1.3 非功能性需求

  • 时效性 (Time-sensitive) - 视频流畅。

  • 扩展性 (Scalability) - 支持世界范围内的海量用户,支持各类设备。

1.4 不需要支持的功能

  • 直播 (Live Video)

2. 资源估算

2.1 假设

  • 50000 小时的内容

  • 200M 订阅

  • 平均每天观看 1 小时,花费约 1GB 流量

2.2 估算

  • 存储 - 50000 * 100 GB (一小时是内容所有尺寸容量的总和) = 5 PB

  • 吞吐量 (Throughput) - 200M * 1GB / 3600 = 56 TB/s

3. High-level Diagram

4. 核心子服务设计

Netflix 的服务可以分成三个大块,上线视频,用户界面,以及视频播放。三者各有其独到之处,下面我们就展开来讲。

4.1 上线视频

Netflix Tech Blog. High Quality Video Encoding at Scale.

4.1.1 视频接收及检验

由于 Netflix 并不是一个 UGC 平台,它的视频源都是拥有大量片源的影视公司如时代华纳。对于这些公司,Netflix 可以提供一系列方法去接收这些片源,比如物理拷贝或是网络上传。

接收这些视频之后,这些片源的源文件就会汇总到 Netflix 的分布式文件系统中去。对于每个视频,我们可以建立一套测试集,使用技术手段去检测文件的完整性,有没有跳帧或是编码错误。

一旦发现文件不能满足要求,就可以将视频接收任务标记为失败,联络上传视频源的公司并清理相关文件。

4.1.2 视频分段

高清片源的体量巨大,一小时内容可以达到数十 GB 大小。为了增加后续编码步骤的效率,我们可以事先将视频切割成较短的段落。

4.1.3 视频再编码

视频编码是一个很消耗资源的任务,所以我们需要引入任务队列 (Task Queue) 和 Worker。完成视频分段后,我们可以把视频的链接以及编码资料 (Encoding Profile) 一起放入任务队列。编码资料会包含如视频文件类型,质量,画面大小,音频文件类型以及字幕语言等等。

一个集群的 Worker 可以依次从任务队列中将任务取出并执行。如果任务执行成功,完成编码的文件会被汇总到分布式文件系统中去。如果失败,可以进行一定次数的重试。

4.1.4 视频部署

视频部署在视频播放章节会再次提到,在这里我们先开个头。

在部署之前,文件已经在分布式文件系统中了。当视频需要被部署的时候(比如新剧马上要被用户看到的时候),我们可以将这些视频文件部署到遍布世界各地的 CDN 中去。这样,用户就不需要到分布式文件系统中调取视频文件,而是可以就近从 CDN 中调取,大大减少骨干网的流量。视频部署因为牵涉到世界范围内的文件调度,会消耗较大的带宽,我们可以考虑在网络流量较小的时候进行。

4.2 用户界面

4.2.1 内容列表的列表 (List of List of Video)

打开 Netflix 的用户界面,我们就能看到一个内容列表的列表。Netflix Interface

该服务会联系多个下游服务,比如以下的这些:

  • 用户信息

  • 订阅会员信息

  • 内容播放历史

  • 自定义的播放列表

  • 流行内容 (Popular)

  • 趋势内容 (Trending)

  • 推荐内容类别

  • 类别内容列表

  • 个性化内容封面

Good Will Hunting Cover Artwork from Todd Hoff. (2017). Netflix: What Happens When You Press Play?Pulp Fiction Cover Artwork from Todd Hoff. (2017). Netflix: What Happens When You Press Play?

其中个性化视频封面是 Netflix 一个比较广为人知的优化。首先 Netflix 对于每个视频内容都会有多个视频封面,根据用户对不同封面的点击频率,Netflix 会挑出点击率高的,并且按照每个人的兴趣爱好来给出特定的封面。举一个例子就很好理解,我们要给电影诺丁山挑选封面。如果用户观看过很多茱莉亚罗伯茨的电影,那么封面就最好突出她;反之如果他是休格兰特的影迷,那么突出休格兰特就更好。当然,真实模型中采用的 Feature 会不止演员一个。

4.2.2 详细内容页

在内容页上,我们会访问以下几个下游服务:

  • 个性化内容封面

  • 内容信息(内容类型 - 剧集或电影,分级,简介)

  • 剧集信息(每季每集简介,封面)

  • 视频播放信息(视频的访问链接)

其中视频播放信息服务值得我们关注,会在下一小节中展开。

4.3 视频播放

4.3.1 下游服务

它也有三个重要的下游服务,订阅会员服务,版权服务以及 CDN 管理服务。

  • 订阅会员服务会在视频播放的开始以及过程中查询会员服务是否仍然有效

  • 版权服务会确认用户所在的地区有权限访问用户选定的内容

  • CDN 管理服务会跟 CDN 保持联系,返回并持续更新 CDN 中最符合用户当前播放状态 (网络速度,屏幕大小)的文件所在的最合适的 CDN 链接。这样做可以使得同时优化用户播放的感官体验以及降低网络总体的带宽使用。

4.3.2 视频播放协议

视频播放的自动调节流媒体播放 (Adaptive Streaming) 应该如何实现呢?在这一小节里,我们不仅会触及服务器端的实现,也会讨论客户端的功能。

首先我们要考虑 Netflix 的应用场景。因为 Netflix 没有直播功能,所以视频播放的延迟 (Latency) 并不重要。注意这里的延迟并不是指造成视频卡顿的延迟,而是视频从被摄像机捕捉到被用户看到的延迟。Streaming Procotol Spectrum from Traci Ruether. (2019). Streaming Protocols: Everything You Need to Know

从上图可以看到,Apple HLS 以及 MPEG-DASH 这样的协议对我们的应用场景已经足够。下面我们就简单介绍一下这两个播放协议的运行机制。

在服务器端,视频被分成一小块一小块,称为 Segment。这些内容会包含不同的规格(清晰度,尺寸等等)。在视频播放的过程中,播放器客户端会使用比特率适应算法 (Adaptive Bitrate Streaming),调整视频的清晰度,在保证视频能够流畅播放的前提下,选择最高的比特率。

这两个协议都是基于 HTTP 的,也就是说客户端在确认了希望获得的具体视频之后,会对每一小段视频分别向服务器发送 HTTP GET Request。encoding.com. DASH Streaming

4.4 CDN

4.4.1 什么是 CDN?

举一个例子。当纸牌屋上线的时候,世界各地的观众在短时间内涌入,开始播放。想象以下一个澳洲的观众,在没有 CDN 的情况下,他会通过骨干网中一条连接澳洲和美洲的海底电缆访问位于美国的 Netflix 服务器,延迟可想而知。当成千上万的澳洲观众同时访问的时候,骨干网会拥挤不堪,甚至影响到所有使用这条海底电缆的用户的使用体验。如果我们引入 CDN,让澳洲的观众可以从澳洲的服务器上直接播放纸牌屋,那么骨干网就不需要传输纸牌屋的内容。不仅节约骨干网的带宽,同时大大降低延迟。

4.4.2 为什么要自研 CDN?

在市面上有很多 CDN 服务,用户可以通过 API 将需要部署到 CDN 中的文件上传。Netflix 能够在普通 CDN 服务的基础上优化些什么呢?

  • 高质量 - 在控制了视频文件端到端(编码 <-> CDN <-> 客户端)的流程之后,视频质量可以优化

  • 高扩展性 - 更广泛地部署 CDN

  • 更便宜 - 因为 Netflix 会占用大量的 CDN 资源,自研可以做成本优化

Netflix 通过对于自身服务和用户的理解,还可以进一步在 CDN 的实现细节做一些更细致的优化。

  • 用户行为预测 - 预测哪些视频会在什么区域被观看,提前在流量低谷时部署未来会被最多播放的视频到相应地区

  • 对视频做定制优化 - 普通 CDN 需要分发网页,音频,图片等多种类型的资源,而 Netflix 的 CDN 可以更简单,只为视频服务

4.4.3 CDN 物理部署Tiered Caching System from Todd Hoff. (2017). Netflix: What Happens When You Press Play? ‌‌

Netflix 将它的 CDN 分成多个级别,级别越高的 CDN 数量越少,包含的视频内容越多。相反,级别越低的 CDN 数量越多,离用户更近。

Netflix 用了很有创意的方法部署它的低级别 CDN (Google 也采用了类似的方法)。它将自己的 CDN 通过免费赠送机器的方法,直接部署到了 IXP 和 ISP 的机房里。通过这样直接在互联网上离用户很近的关键节点上部署自己的 CDN,Netflix 跟 ISP/IXP 达到了双赢。一方面 Netflix 可以降低客户端的延迟,另一方面 ISP/IXP 可以将节约下的带宽用来支持非 Netflix 的流量。

因为这些 IXP/ISP 机房中的微 CDN 不能存储 Netflix 所有的内容,之前提到的用户行为预测就有了用武之地。同时,大型 CDN 中因为存储了所有内容,客户端永远不需要直接访问分布式文件系统去读取视频文件。

在拥有了众多的 CDN 之后,Netflix 的视频服务变得非常稳定。即使在多个 CDN 站点同时宕机的情况下,剩下的数量庞大的 CDN 可以继续为用户提供高质量的服务。

4.4.4 视频播放流程Todd Hoff. (2017). Netflix: What Happens When You Press Play?‌‌

让我们回顾一下视频播放的流程:

  1. 用户选择一个视频,点击播放。

  2. 会员服务以及版权服务确认用户可以播放该内容。

  3. 视频播放服务根据用户所在的网络情况挑选出一组包含该内容的 CDN 服务器。

  4. 客户端持续联系这一系列服务器来找到最稳定最快速的连接。

  5. 客户端连接到最合适的服务器,并开始播放视频。

  6. 客户端在播放过程中,根据网络情况持续调节视频质量。在有需要的时候,重新找到合适的 CDN 获取视频。

5. 数据结构与存储

5.1 视频存储

  • Object Store - Amazon S3 / GFS / HDFS

  • CDN - OpenConnect / Akamai

5.2 用户数据库

Cache & DB

Subscriber ID | Subscriber Name | Renewal Status | Subscription Expiration Date | Subscriber Email...

6. 接口设计

6.1 视频播放

Apple HLS / MPEG-DASH

6.2 内容列表列表 (List of List of Movie)

HTTP GET api/v1/list_of_list?user_id=acecodeinterview

6.3 详细内容页

HTTP GET api/v1/content_detail?content_id=c0

7. 扩展性

  • 世界范围内广泛分布的 CDN 尽可能降低延迟

  • 视频文件的原本存储在分布式文件系统中

  • 使用分布式数据库如 Cassandra 或 DynamoDB

  • 使用分布式缓存如 Redis 或 Memcached

8. 监控和警报

  • 视频编码队列健康度

  • 异步视频编码 worker 负载

  • 每个 CDN 的缓存命中率

  • 使用骨干网的带宽

  • 平均视频播放时长

  • 订阅用户数量

  • 数据库使用比例

  • 文件系统使用比例

9. 参考资料

Last updated