# 在 30 分钟内进行 7 年的 YouTube 可扩展性课程

> 原文： [http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html](http://highscalability.com/blog/2012/3/26/7-years-of-youtube-scalability-lessons-in-30-minutes.html)

![](img/037ab09a00de464dc99a6ba677f01263.png)

如果您开始建立约会网站，而最终建立了每天处理 40 亿次观看次数的视频共享网站（YouTube），那么您可能会在此过程中学到一些东西。 确实，YouTube 的原始工程师之一 Mike Solomon 确实学到了很多东西，他在 [PyCon](https://us.pycon.org/2012/) ： [在 YouTube 上的可扩展性上做了演讲](http://www.youtube.com/watch?v=G-lGCC4KKok) 。

这不是架构驱动的讨论，我们将通过介绍许多盒子相互连接的方式进行介绍。 迈克可以这样讲。 他致力于建立 YouTube 的 Servlet 基础结构，视频索引功能，视频转码系统，全文搜索，CDN 等。 但是，相反，他退后了一步，仔细研究了工作时间，并分享了一些深刻的经验教训，这些经验教训显然是来之不易的。

对我来说，要讲的主要内容是使用非常简单的工具完成了**。 尽管许多团队都在转向更复杂的生态系统，但 YouTube 确实做到了简单。 他们主要使用 Python 进行编程，使用 MySQL 作为其数据库，他们一直使用 Apache，甚至对于一个如此庞大的站点来说，新功能都始于非常简单的 Python 程序。

这并不意味着 YouTube 不会做酷的事情，而是做的，但是使所有事情协同工作的更多的是哲学或做事方式，而不是技术专长。 是什么使 YouTube 成为世界上最大的网站之一？ 继续阅读并查看...**

## 统计信息

*   每天 40 亿次观看
*   每分钟上传 60 个小时的视频
*   350+百万台设备启用了 YouTube
*   2010 年收入翻了一番
*   视频的数量增加了 9 个数量级，而开发人员的数量仅增加了 2 个数量级。
*   一百万行 Python 代码

## 堆栈

*   **Python-** YouTube 的大部分代码行仍在 Python 中。 每次观看 YouTube 视频时，您都在执行一堆 Python 代码。
*   **Apache** -当您认为需要摆脱它时，则不需要。 Apache 是​​YouTube 上真正的摇滚明星技术，因为它们保持了简单。 每个请求都通过 Apache。
*   **Linux** -Linux 的好处是总有一种方法可以进入并查看您的系统运行情况。 无论您的应用程序表现多么糟糕，您都可以使用 strace 和 tcpdump 之类的 Linux 工具对其进行查看。
*   **MySQL** -使用很多。 观看视频时，您正在从 MySQL 获取数据。 有时它使用关系数据库或 Blob 存储。 这是关于调整和选择组织数据的方式。
*   [**Vitess**](http://code.google.com/p/vitess/) -YouTube 发布的新项目，用 Go 编写，它是 MySQL 的前端。 它动态地进行了很多优化，它重写查询并充当代理。 目前，它可以处理每个 YouTube 数据库请求。 它基于 RPC。
*   **Zookeeper** -分布式锁定服务器。 用于配置。 真正有趣的技术。 难以正确使用，因此请阅读手册
*   **Wiseguy** -一个 CGI Servlet 容器。
*   **Spitfire** -一个模板系统。 它有一个抽象的语法树，让他们进行转换以使处理更快。
*   **序列化格式** -无论使用哪种格式，它们都非常昂贵。 测量。 不要用泡菜 不是一个好选择。 找到的协议缓冲区很慢。 他们编写了自己的 BSON 实现，比您可以下载的实现快 10-15 倍。

## 一般课程

*   YouTube 的 **Tao** ：选择最简单的解决方案，并附带最实际的保证。 您需要所有这些东西的原因是您需要灵活性来解决问题。 在您指定的那一刻，您就会把自己粉刷成一个角落。 您不会做出这些保证。 尝试做出所有这些保证时，您的问题会自动变得更加复杂。 您不会离开自己。
*   **整个过程就是**的可伸缩性。 可扩展的系统是您所无法企及的。 您没有意识到。 这不是流行语。 这是解决精神问题的一般问题。
*   **大型系统设计的标志**：每个系统都是根据其特定要求量身定制的。 一切都取决于构建的细节。
*   **YouTube 不是异步的**，所有内容都处于阻塞状态。
*   **相信哲学胜于教义**。 简单点。 那是什么意思？ 当您看到它时，您就会知道。 如果执行代码检查会更改数千行代码和许多文件，则可能是一种更简单的方法。 您的第一个演示应该很简单，然后进行迭代。
*   **解决一个问题：一个字-简单**。 寻找最简单的方法来解决问题空间。 有很多复杂的问题，但是第一个解决方案并不需要复杂。 随着时间的流逝，复杂性自然会到来。
*   **许多 YouTube 系统都是从一个 Python 文件**开始的，并在许多年后变成了大型生态系统。 他们所有的原型都是用 Python 编写的，并且存活了惊人的时间。
*   **在设计审查**中：
    *   什么是第一个解决方案？
    *   您打算如何迭代？
    *   我们对该数据将如何使用了解多少？
*   **事情随时间而变化**。 YouTube 如何起步与以后发生的事情无关。 YouTube 最初是一个约会网站。 如果他们为此设计，他们将有不同的对话。 保持灵活性。
*   **YouTube CDN** 。 最初是外包出去的。 非常昂贵，所以他们自己做。 如果您有不错的硬件伙计，则可以构建一个不错的视频 CDN。 您建立了一个非常大的机架，将机器插入其中，然后进行 lighttpd 处理，然后覆盖 404 处理程序以查找未找到的视频。 这花了两个星期的时间，而且第一天的服务量为 60 吉比特。 使用非常简单的工具，您可以做很多事情。
*   **您必须测量**。 Vitess 换出了一个协议来进行 HTTP 实现。 即使在 C 语言中，它的速度也很慢。 因此，他们剥离了 HTTP 并使用 python 进行了直接套接字调用，这在全局 CPU 上便宜了 8％。 HTTP 的封装确实非常昂贵。

## 可扩展性技术

*   这些不是新主意，但令人惊讶的是，一些核心主意如何在许多不同的方面得到应用。
*   **分而治之-可伸缩性技术**
    *   这是可伸缩性技术。 一切都是关于划分工作。 确定如何执行它。 从 Web 层开始，适用于许多事物，您拥有许多 Web 服务器，这些 Web 服务器或多或少完全相同且独立，并且可以水平扩展它们。 那是分而治之。
    *   这是数据库分片的关键。 您如何划分内容，并在细分的部分之间进行交流。 这些是您想尽早解决的事情，因为它们会影响您的成长方式。
    *   简单而松散的连接确实很有价值。
    *   Python 的动态特性在这里是一个胜利。 不管您的 API 有多糟糕，您都可以存根或修改或修饰自己的方式来解决许多问题。
*   **近似正确性-稍作弊**
    *   另一个喜欢的技术。 系统的状态就是它所报告的状态。 如果用户不能告诉系统的一部分是歪斜和不一致的，那不是。
    *   一个真实的例子。 如果您写评论，但有人同时加载该页面，则他们可能会在 300-400 毫秒内没有收到该评论，正在阅读的用户将不在乎。 评论的作者会在意，因此您确保撰写评论的用户会看到它。 所以你有点作弊。 您的系统不必具有全局一致的交易记录。 那将是非常昂贵和过度的。 并非每条评论都是金融交易。 所以知道什么时候可以作弊。
*   **专家旋钮切换**
    *   问，您对一致性模型了解多少？ 对于评论的最终一致性是否足够好？ 租电影是不同的。 租房时有钱，所以我们会尽力做到永不丢失。 根据数据需要不同的一致性模型。
*   **抖动-向系统中添加熵**
    *   始终是他们小组中的热门词。 如果您的系统没有抖动，那么您会得到 [雷电群](http://highscalability.com/blog/2008/3/14/problem-mobbing-the-least-used-resource-error.html) 。 分布式应用程序实际上是天气系统。 调试它们与确定天气一样具有确定性。 抖动引入了更多的随机性，因为令人惊讶的是，事情趋于堆积。
    *   例如，缓存过期。 对于流行视频，他们会尽其所能地缓存内容。 他们可能会缓存 24 小时的最受欢迎的视频。 如果所有内容一次到期，则每台计算机将同时计算到期时间。 这产生了一个雷电群。
    *   抖动表示您在 18-30 小时之间随机失效。 这样可以防止事情堆积。 他们在各处使用它。 当操作排队并试图破坏自身时，系统倾向于自我同步。 令人着迷的观看。 一台计算机上的磁盘系统运行缓慢，每个人都在等待一个请求，因此所有其他计算机上的所有其他请求突然之间完全同步。 当您有很多机器并且有很多事件时，就会发生这种情况。 每个人实际上都从系统中删除了熵，因此您必须重新添加一些熵。
*   **作弊-知道如何伪造数据**
    *   很棒的技术。 最快的函数调用是不会发生的。 当您拥有一个单调递增的计数器（例如电影观看次数或个人资料观看次数）时，您可以在每次更新时进行一次交易。 或者，您可以不时进行一次交易，并随机更新一次，只要交易从奇数变为偶数，人们可能会认为这是真实的。 知道如何伪造数据。
*   **可扩展组件-自己创造运气**
    *   **您可以查看一个 API 并获得良好的感觉**。 输入是否定义明确？ 你知道你要出去吗？ 其中很多最终都与数据有关。 严格说明每个函数将输出什么数据以及它如何流动，实际上可以帮助您在没有文档的情况下理解应用程序。 您可以分辨出在调用函数之前和之后发生的情况。
    *   **在 Python 中，事情倾向于向 RPC** 发展。 代码的结构基于程序员的纪律。 因此要建立良好的约定，当所有其他方法都失败时，就会出现 RPC 隔离墙，以便您了解其中的内容和结果。
    *   **您的组件将不完美**。 知道，一个组件可能会持续一个月或六个月。 通过画出这些线条，您正在自己赚一些钱。 当事情发展到南方时，您可以将其换成其他东西。 有时用 python 和 C 重写某些内容，有时则意味着完全摆脱它。 直到您能够观察到，您才知道。
    *   **团队中有这么多人，没人知道整个系统**，因此您需要定义组件。 这是视频转码，与视频搜索不同。 您需要定义明确的子组件。 好的软件设计。 这些事情最终导致彼此交谈，因此拥有一个良好的数据规范将很有帮助。 他最大的罪过是 Servlet 层和模板层之间的通信，使之成为字典。 好主意。 应该添加一个 WatchPage 并说一个观看页面有一个视频，一些评论和一些相关视频。 这引起了很多问题，因为字典可以具有数百个属性。 他们并不总是做出正确的选择。
*   **效率-以可扩展性为代价**
    *   **效率是以可伸缩性** 为代价的。 最有效的方法是用 C 编写并将其塞入一个进程，但这是不可扩展的。
    *   **关注宏级别** **，您的组件以及它们如何分解**。 将此做为 RPC 还是以内联方式有意义？ 将其分成一个子包，就可能有一天可能会有所不同。
    *   **关注算法** 。 在 Python 中，实现良好算法的工作量很低。 例如，有 bisect 模块，您可以在其中获取列表，做一些有意义的事情，并将其序列化到磁盘上，然后再次读回。 对 C 有罚款，但这很容易。
    *   **测量** 。 在 Python 中，测量就像阅读茶叶一样。 Python 中有很多与直觉相反的东西，例如抓斗成本。 他们的大多数应用程序都花时间进行序列化。 对序列化进行概要分析非常取决于您要插入的内容。对 int 进行序列化与对大 blob 进行序列化有很大不同。
*   **Python 的效率-知道不该做什么**
    *   **有关了解不要做什么的更多信息** 。 您制作事物的动态程度与运行 Python 应用程序的昂贵程度相关。
    *   **Dummer 代码更易于 grep 且易于维护** 。 代码越神奇，就越难弄清楚其工作原理。
    *   **他们并没有做很多 OO** 。 他们使用很多命名空间。 使用类来组织数据，但很少用于 OO。
    *   **您的代码树是什么样的？** 他希望用以下词语来形容它：简单，实用，优雅，正交，可组合。 这是一个理想，现实有点不同。

## 相关文章

*   [使用 Python 调整 YouTube 大小](http://www.slideshare.net/didip/super-sizing-youtube-with-python)
*   [扩展 Web 的 MySQL 数据库](http://www.percona.com/live/mysql-conference-2012/sessions/scaling-mysql-databases-web)
*   [YouTube 架构](http://highscalability.com/youtube-architecture)
*   [关于 HackerNews](http://news.ycombinator.com/item?id=3757456)

不错。 可以使用一些校对方法，因为我不得不在某些语言被弄乱的地方放慢脚步，例如“那些东西你想早点弄清楚，因为它们会影响你的成长方式。” 否则，有趣的阅读使我想给 python 多一点关注。

嗯，但公平地说，YouTube 使用 lighttpd 吗？ 通过萤火虫：http://i.imgur.com/ClSH4.png

“ Apache 是​​YouTube 上真正的摇滚明星技术，因为它们使它保持简单。每个请求都通过 Apache 进行。”

“您建立了一个非常大的机架，将机器插入其中，然后进行 lighttpd”

如果 Apache 很棒，为什么他们选择 lighttpd 代替呢？

这是否还意味着“每个请求都通过 Apache”的语句不正确？

好文章。 还有一些 UX 良好做法。

@ Michal，@ Andy：这些语句是在 CDN 的上下文中的，因此您可以假定它们意味着 CDN 将 lighttpd 用于静态内容，而将 Apache 用于其余内容。

前 YouTuber 在这里...

Apache 是​​他们处理动态 Web 请求的方式。 主页，观看页面，用户页面等。在早期，视频流媒体，视频上传者和图像上传者在 Lighthttpd 上运行，因为它能够更好地处理非交互式数据流。

当我两年多前离开时，他们正处于将大多数视频流切换到基于 Google 的基础架构的过程中，因为 Google 基础架构具有对等协议和更高的带宽成本。 在此过程中，他们似乎决定保留旧的视频流，并将其用于静态内容服务（Lighthttpd 做得很好）。

顺便提及，随机更新事物最近已获得专利。

@michal @andy，听起来好像 apache 是​​他们的 Web 服务器，而 lighttpd 驱动了 CDN，因此在外部您会收到 lighttpd 标头，但 apache 确实在做这项工作。

作为对 YouTube 的致敬，您可以将其制作成 30 分钟的视频吗？ 大声笑

您可以同时使用 apache 和 lighttpd 来实现目标。 如果这篇文章更详细地解释每一个 YouTube 服务的内容，那将是很好的。 看起来.ligspd 至少提供了.css 文件，这是其静态内容。

“ YouTube 不是异步的，一切都在阻塞。” 为什么？ 我以为大家都同意，最好的办法就是去医院。

也许它可以防止出现错误：
“所有形式的异步 I / O 都会打开应用程序，直至出现潜在的资源冲突和相关的故障。需要仔细的编程（通常使用互斥，信号量等）来防止这种情况。”

资料来源：http://en.wikipedia.org/wiki/Asynchronous_I/O

谈到简单而可靠的工具：Youtube 什么时候切换到 PostgreSQL？

感谢您的出色总结！

哇，什么是“夏季代号”？