如何设计一个 Youtube 系统
简化这个复杂的系统设计问题,把它分成几块:
- 存储:数据库如何设计,图片和视频如何存储
- 扩展:面对百万级别甚至上亿级别的用户,如何扩展存储和整个系统
- Web 服务器:前端与服务器沟通进行用户验证,Session,取数据和更新用户数据等等,然后服务器与存储系统,推荐系统等等再沟通
- 缓存:我们需要多个层次的缓存
- 还有很多问题,比如推荐系统,安全系统等等,每一个问题都可以当成一个面试题
存储和数据模型
首先,我们需要定义用户数据模型,我们可以把 email ,姓名,注册信息等等存储在一个表里面。另外一种更常见的做法就是把用户数据拆成两个表,一个专门为了验证,存储 email ,密码,姓名,注册日期之类的,另外一个存储更详细的信息,例如地址,年龄等。
视频也一样,它包括一些基本信息。很明显,我们也应该把这些基本信息存储在一个独立的表里面。
另外需要的就是用户喜欢的视频和用户关联的视频,这两部分信息需要单独建表。
视频和图片存储
其实 Youtube 的图片数量比视频数量要多,因为每个视频都有好几个不同大小的thumbnails,所以图片存储不可忽视。比较常见的做法就是使用 CDN 了。
热门 vs 冷门视频
如果你觉得把所有视频和图片都扔到 CDN 上,那你就大错特错了,大多数视频都是 long-tailed 冷门视频,一天也就 1-20 个观看。然而转念一想,这些热门视频随处可见,倒是一些冷门视频才让一个产品变得与众不同,吸引特定的一部分群体。如果你能提前预测的话,那么高效地存储这部分信息也是有可能的。
数据库扩展
- 首先仅当你确实需要扩展数据库的时候,你才去扩展数据库。
- 当业务发展到一定规模之后,可能会拥有一个master和几个slavesmaster/slave model)。
- 再往后,你可能会拆分数据库,开始着想sharding方法。例如,你可以根据用户的位置来拆分数据库,当一个请求进来的时候,你可以路由到相应的数据库去。
对于 Youtube 来说,我们还可以进一步优化。我们一定要分清楚瓶颈在哪里,在这里就是观看视频,通过把数据拆分成两个集群:视频集群和general集群,我们可以把更多的流量分给视频集群,其他行为相应的路由到能力较弱的这个集群上。
数据缓存
鉴于我们先前已经探讨过如果设计一个缓存系统,所以这里不多做介绍,但是有几个地方需要注意:
- 一般人会想到服务器缓存,但前端缓存同样重要。如果你想让你的网站非常快速,前端缓存几乎不可避免。
- 另外,Youtube 一般使用 long-tailed 用户比较多,把所有视频缓存起来很不现实。
安全
在安全问题上有很多可以考虑,我在这里提一下观看数量的问题。
- 当一个 IP 有太多对数量接口的请求的时候,我们就屏蔽掉这个 IP
- 我们甚至可以限制每个 IP 最多可以观看的数量
- 也可以查看浏览器agent和历史记录,来预防一部分潜在攻击
- 人们可以使用Tor)来隐藏IP,或者使用Mechanical Turk来刷榜
- 一个观看数量只多,但是其他分享数量、评论数量、观看时间不多的视频,也是比较可疑的
Web 服务器
许多人大概都忽视了 Web 服务器,实际上还是有很多事情需要考虑的。
- Youtube 一开始选择使用
Python
来快速开发,虽然性能有点慢,但是可以通过C extensions
来解决。 - 为了扩展Web服务器,你可以有多个replicas(A replica is an exact reproduction, such as of a painting, as it was executed by the original artist or a copy or reproduction, especially one on a scale smaller than the original),然后建一个load-balancer在它们之上
- Web 服务器响应速度必须快
How to Design Youtube (Part I) How to Design Youtube (Part II) Wikipedia-Replica