Netflix系统架构

2021-12-25  本文已影响0人  DeepNoMind

Netflix是全球最大的在线视频网站之一,它是怎么设计的呢?这篇文章介绍了Netflix系统架构的设计方案。原文:Netflix System Architecture[1]

我们来讨论一下如何设计Netflix。

相信每个人都会通过某些网站或应用在线追剧或者看电影,而Netflix是我最喜欢的在线视频网站,不过今天我不推荐任何电影,相反,我想展示的是Netflix背后令人惊艳的系统逻辑。


功能性需求

  1. 创建帐户、登录、删除帐户
  2. 订阅或取消订阅不同的计划
  3. 允许用户拥有和处理多个帐户
  4. 允许用户观看视频
  5. 允许用户下载视频并离线观看
  6. 允许用户通过视频标题搜索和发现视频
  7. Netflix制作人可以从后台上传视频并在平台上展示
  8. 平台可以显示趋势、最受欢迎的视频和分类,以方便用户选择
  9. 可以选择不同语言的字幕,这样用户即使听不懂这些语言,也可以观看视频
  10. 视频分组(剧集、娱乐节目、电影,单独处理每个视频)
  11. 根据用户行为进行分析,为用户推荐类似的视频
  12. 在同一账号下的不同设备之间进行同步,用户可以使用不同的设备继续观看同一视频而无需重播
  13. 支持全天候(24/7)回放
  14. 支持回退

非功能性需求

  1. 用户可以观看实时视频流,没有任何卡顿或延迟问题
  2. 系统是高度可靠的
  3. 高可用
  4. 可扩展
  5. 视频数据持久化且易于访问

容量预估

我们可以基于一些数学计算来估计所需的带宽和存储空间。

假设
  1. 日活用户总数 = 1亿
  2. 日活峰值用户:1亿 * 3 = 3亿
  3. 3个月最大日活峰值用户:3亿 * 2 = 6亿
  4. 每个用户每天平均观看的视频数 = 5
  5. 视频平均大小 = 500 MB
  6. 后台平均每天上传的视频数 = 1000
  7. 每天观看的总视频数 = 1亿*5 = 5亿
  8. 每天观看的总视频峰值 = 15亿
  9. 每天观看的最大视频峰值 = 30亿
  10. 每天总出口流量 = 5亿* 500 MB = 250 PB (Peta Byte)
  11. 出口带宽 = 29.1 GB/秒
  12. 每天上传总入口流量 = 1000 * 500MB = 500 GB
  13. 入口带宽 = 5.8 MB/秒
  14. 5年所需的总存储空间 = 500 GB * 5 * 365 = 912.5 TB(请注意,Netflix会为每个视频准备多种格式和分辨率的版本,可针对不同类型设备进行优化,所以存储空间将超过912.5 TB)。

系统组件

系统组件详细设计

1. 客户端应用

基于React.js实现的前端可以拥有较好的加载/启动速度、持久性/模块化和运行时性能。

2. 后端

Netflix从2011年开始实施微服务架构,完全基于云来管理工作负载。通过小型、可管理的API组件支持并处理来自应用程序和网站的请求,微服务内部通过请求和获取数据而相互依赖。后端技术栈包括了Java, MySQL, Gluster, Apache Tomcat, Chukwa, Cassandra, KAFKA和Hadoop。后端系统不单单需要处理流媒体视频,还需要处理其他所有事情,比方说数据处理、加载新内容、网络流量管理、全球资源分发等。Netflix目前部署在AWS之上。

数据处理涉及点击视频后发生的所有事件,系统需要在几纳秒的时间内处理完视频并将其传输给用户。整个系统每天大约需要处理6000亿个事件,产生1.5PB的数据,在高峰期(傍晚和夜间)每秒大约需要处理800万个事件。这些事件包括UI活动、视频查看活动、日志错误、故障排除、诊断事件、处理事件和性能事件等。所有这些事件都是通过Kafka和Apache Chukwe完成的。

Kafka和Apache Chukwe

Elastic Search

后端服务

3. 云

4. CDN

一个全球分布的服务器网络集群。当我们播放视频的时候,设备上显示的视频将从最近的CDN服务器获取,从而极大降低响应时间。

5. Open connect[2]

Netflix的内部定制全球CDN,负责向全球Netflix用户存储和传送电影和电视节目。当我们按下播放按钮,视频就会从全球不同位置的Open connect服务器中传输给我们。如果视频已经缓存在Open connect服务器上,客户端可以轻松访问到,而如果视频没有被缓存,Netflix必须从AWS的S3存储中获取并处理该视频,然后Open connect才可以将该视频流推送到客户端应用程序。

6. 缓存

Redis和Memcached以键值对的方式缓存数据库中的数据,可以有效减少对数据库的访问。客户端通过服务器访问数据库之前,系统会检查缓存中是否有数据,如果有,就可以绕过数据库访问。但是,如果数据不在缓存中,必须访问数据库并获取数据,并在缓存中填充相同的数据。因此,随后的请求就不需要访问数据库了。这种缓存策略称为绕写(write-around)缓存。我们使用最近最少使用(LRU)策略作为缓存数据的驱逐策略,最早获取的缓存将会被丢弃。

Netflix在AWS EC2上部署了很多集群,这些集群包含有很多Memcached节点以及缓存客户端。数据在同一个分区的集群中共享,多个缓存副本存储在分片节点中。每次当客户端写入数据时,所有集群中的所有节点都会被更新,但当读取数据时,读取操作只会被发送到最近的集群及其节点上,如果某个节点不可用,则从另一个可用节点读取。这种方法提高了性能、可用性和可靠性。

7. 可扩展性

8. 安全

9. 弹性

10. 负载均衡

负载均衡器负责将流量路由到前端服务。ELB(Elastic load balancing,弹性负载均衡)执行两层负载均衡方案,首先基于区域(zone)进行负载均衡,然后对实例(服务器)进行负载均衡。

11. Geo-redundancy

12. ZUUL

提供动态路由、监控、弹性和安全性,支持基于查询参数、URL路径的简单路由。

优势:

  1. 可以创建规则,将流量的不同部分分配到不同的服务器,从而实现对流量的分片
  2. 开发人员可以在某些机器上对新部署的集群进行负载测试,可以在这些集群上路由部分现网流量,并检查特定服务器可以承受多少负载。
  3. 可以用于测试新服务。当我们需要升级服务并希望检查该服务如何处理实时API请求时,可以将特定服务部署在一台服务器上,并将部分流量重定向到新服务,以便实时检查该服务状态。
  4. 可以通过在端点过滤器或防火墙上设置自定义规则来过滤恶意请求

13. Hystrix

在一个复杂的分布式系统中,一个服务器可能依赖于另一个服务器的响应。这些服务器之间的依赖关系可能会造成延迟,如果其中一个服务器在某个时刻不可避免的出现故障,整个系统可能都会停止工作。为了解决这个问题,可以将主机应用程序与这些外部故障隔离开来。Hystrix库就是为此而设计的,通过添加延迟容忍和容错逻辑,帮助我们控制分布式服务之间的交互。Hystrix通过隔离服务、远程系统和第三方库之间的访问点来实现这一点。Hystrix可以帮助我们实现:


数据库组件

Netflix使用不同的DB来存储不同类型的文件,例如用于不同目的的SQL和NoSQL。

1. MySQL

2. Cassandra (NoSQL)

数据库定义


API

用户注册

请求:

POST /api/v1/users
X-API-Key: api_key
{
  name:
  email:
  password:
}

通过HTTP POST方法,在数据库中创建一个资源或新条目。X-API-Key是传递给HTTP报头的API key,用于识别不同的客户端并进行速率限制。

响应:

201 Created
{
  message:
}

HTTP状态码201告诉用户已成功注册。用于失败情况的其他可能的HTTP状态码:

400 Bad Request
409 Conflict
500 Internal Server Error

用户登录

请求:

POST /api/v1/users/session
X-API-Key: api_key
{
  email:
  password:
}

响应:

200 OK
{
  auth_token:
}

API应该返回一个auth_token,它可以在header中传递给需要认证的后续API调用。auth_token可以使用JWT[3]生成。

用户登出

请求:

DELETE /api/v1/users/session
X-API-Key: api_key
Authorization: auth_token

使用HTTP DELETE方法删除数据库中的行条目,意味着我们正在终止一个会话。

响应:

200 OK

HTTP状态码200表示成功登出。

订阅

请求:

POST /api/v1/subscription
X-API-Key: api_key
Authorization: auth_token

HTTP POST方法创建一个新的订阅,在Authorization头中传递auth-token来验证用户。

响应:

201 Created
{
  subscription_id:
  plan_name:
  valid_till:
}

HTTP状态码201与subcription_id、plan_name和valid_till一起在用户界面中呈现。

可能的HTTP失败状态码:

401 Unauthorized
400 Bad request

取消订阅

请求:

DELETE /api/v1/subscription
X-API-Key: api_key
Authorization: auth_token

HTTP DELETE方法是可以取消订阅,该接口将从订阅数据库中删除一个行条目。

响应:

200 OK

HTTP状态码200意味着成功完成。

批量获取视频

请求:

GET /api/v1/videos?page_id=<page_id>
X-API-Key: api_key
Authorization: auth_token

该API用于在登录后呈现主页,包含了由机器学习模型确定的推荐视频。page_id用于API中的分页,next_page_id用于从下一页请求结果。

响应:

200 OK
{
  page_id:
  next_page_id:
  videos: [
    {
      id:
      title:
      summary:
      url:
      watched_till:
    },...
  ]
}

HTTP状态码200表示操作成功。

其他故障状态码:

401 Unauthorized
500 Bad request
429 Too many requests

HTTP状态码429意味着用户达到速率限制,需要等待一段时间才能再次发出请求,以避免拒绝服务攻击。

搜索API

请求:

GET /api/v1/search?q=<query>&page_id=<page_id>
X-API-Key: api_key
Authorization: auth_token

通过标题搜索视频。

响应:

200 OK
{
  page_id:
  next_page_id:
  videos: [
    {
      id:
      title:
      summary:
      url:
      watched_till:
    },...
  ]
}

HTTP状态码200表示操作成功,响应中包括了id、title、summary、url和watched_till等信息,不过也有可能找不到相关视频。

获取视频

请求:

GET /api/v1/videos/:video_id
X-API-Key: api_key
Authorization: auth_token

播放特定视频。

响应:

200 OK
{
  id:
  title:
  summary:
  url:
  watched_till:
}

HTTP状态码200表示匹配到了视频。

其他故障状态码:

401 Unauthorized
404 Video not found
429 Too many requests
500 Internal server error

上传API

请求:

POST /api/v1/videos
X-API-Key: api_key
Authorization: auth_token
{
  title:
  summary:
  censor_rating:
  video_contents:
}

从后台上传视频。

响应:

202 Accepted
{
  video_url:
}

HTTP状态代码202表示视频已经排队进行异步处理和质量检查,处理结果可以通过电子邮件或其他告警机制发送给用户。

一些HTTP失败的场景:

401 Unauthorized
400 Bad request
500 Internal server error

更新观看时间戳

请求:

PUT /api/v1/videos/:video_id/watched_till
X-API-Key: api_key
Authorization: auth_token
{
  watched_till:
}

之所以使用HTTP PUT方法,是因为我们需要用其他数据替换同一个数据库表中的行条目,或者我们需要更新服务器上的资源。这个API将用于更新时间戳,直到用户看完了特定的视频。

响应:

200 OK

HTTP状态码200表示操作成功。

其他HTTP失败状态码:

401 Unauthorized
400 Bad request
500 Internal server error

微服务架构

由于服务中的任何更改都可以很容易完成,因此微服务可以更快的完成部署。可以跟踪每个服务的性能,如果有任何问题,则可以快速将其与其他正在运行的服务隔离开来。

  1. 关键服务——为经常与该服务交互的用户提供服务。这些服务独立于其他服务,以便在进行任何故障转移时,用户可以继续执行基本操作。
  2. 无状态服务——向客户端提供API请求,即使有任何服务器出现故障,也可以继续与其他实例一起工作,从而确保高可用性。例如,REST API服务为最多的用户提供服务。

上传内容

上传的内容是视频格式的电影或剧集,处理单元包括了输入协议、输入编解码器、输出编解码器和输出协议,以服务于各种设备和不同的网络速度。当我们在高速网络上观看视频时,视频的质量很好。Netflix为同一部电影创建不同分辨率的多个副本(大约1100-1200个)。Netflix将原始视频分成不同的小块,并在AWS中使用并行工作单元将这些小块转换成不同的格式。这些处理单元用于编码或转码,即将视频从一种格式转换为另一种格式,如改变分辨率,高宽比,减少文件大小等。在转码之后,一旦我们拥有同一电影的多个文件副本,这些文件就被传输到Open connect服务器。


系统架构概要设计


数据架构


电影推荐

更多资源

  1. https://towardsdatascience.com/deep-dive-into-netflixs-recommender-system-341806ae3b48
  2. https://netflixtechblog.com/announcing-suro-backbone-of-netflixs-data-pipeline-5c660ca917b6
  3. https://keypointt.com/2020-05-16-Netflix-playback-dive-deep/
  4. https://www.nexsoftsys.com/articles/how-netflix-backend-system-operates.html
  5. https://elatov.github.io/2021/02/distributed-systems-design-netflix/
  6. https://developpaper.com/design-and-analysis-of-netflix-microservice-architecture/
  7. https://uxdesign.cc/netflix-system-design-ef5802426ad4
  8. https://netflixtechblog.com/tagged/cloud-architecture
  9. https://www.codingninjas.com/blog/2020/12/04/learn-what-is-rest-api-in-10-minutes/
  10. https://about.netflix.com/en/news/how-netflix-works-with-isps-around-the-globe-to-deliver-a-great-viewing-experience
  11. https://www.infoq.com/news/2019/01/netflix-evolution-architecture/
  12. https://www.codekarle.com/system-design/netflix-system-design.html
  13. http://highscalability.com/blog/2015/11/9/a-360-degree-view-of-the-entire-netflix-stack.html
  14. https://www.youtube.com/watch?v=lYoSd2WCJTo

References:
[1] Netflix System Architecture: https://medium.com/interviewnoodle/netflix-system-architecture-bedfc1d4bce5
[2] Netflix Open Connect: https://openconnect.netflix.com/en/
[3] JSON Web Tokens Introduction: https://jwt.io/introduction/

你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。
微信公众号:DeepNoMind

上一篇 下一篇

猜你喜欢

热点阅读