【译】YouTube 架构
这篇文章摘自 high scalability 网站最受欢迎的文章之一。本文以干货满满地方式介绍了 YouTube 的架构,对网络服务、视频服务、数据存储遇到的难题、解决方法以及如何发展进行了介绍。虽然行文比较简洁,但还是简明扼要地提供了问题解决的思路和方法。有些解决问题的操作也会让人惊呼,原来还可以这样?!但是不管白猫黑猫,能抓耗子的就是好猫。
对于项目经验较少的读者,可以做个指引,对一些可能出现的困境会有所了解;对于有一定大型项目经验的读者,可以提供参照,引起共鸣,可能还会有抛砖引玉的效果。
因为文章写作时间稍微久远,所以一些技术栈已经比较陈旧,有些甚至不再维护;但是解决思路还是有参照意义的。
写作于 2008 年 3 月 12 日星期三下午 3:54
YouTube 增长得非常快,每天的视频浏览量超过 1 亿次,只有少数人负责扩展网站。他们是如何实现将所有视频提供给所有这些用户的?自从被谷歌收购后,它们又是如何演变的?
信息来源
平台
包括什么?
统计数据
每天提供超过 1 亿个视频
成立于 02/2005
2006 年 3 月, 3000 万次视频观看/天
2006 年 7 月, 1 亿次视频观看/天
2 名系统管理员,2 名可扩展性软件架构师
2 名功能开发人员,2 名网络工程师,1 名 DBA
应对快速增长的秘诀
这个循环每天运行很多次。
网络服务器
NetScalar 用于负载均衡和缓存静态内容。
使用 mod_fast_cgi 运行 Apache。
请求被路由以供 Python 应用程序服务器处理。
应用程序服务器与各种数据库和其他信息源对话,以获取所有数据并渲染 html 页面。
通常可以通过添加更多机器来扩展 Web 层。
Python web 代码通常不是瓶颈,它大部分时间都花在了 RPC 上。
Python 允许快速灵活的开发和部署。鉴于他们面临的竞争,这一点至关重要。
通常小于 100 毫秒的页面服务时间。
使用 psyco,一个动态的 python->C 编译器,它使用 JIT 编译器方法来优化内部循环。
对于加密等 CPU 密集型运算,他们使用 C 扩展。
一些预先生成的缓存 HTML 用于渲染块。
数据库中的行级缓存。
完全组装好的 Python 对象被缓存。
计算一些数据并将其发送到每个应用程序,以便将这些值缓存在本地内存中。这是一个未被充分利用的策略。最快的缓存在您的应用程序服务器中,将预先计算的数据发送到您的所有服务器不需要太多时间。只需有一个代理来监视更改、预先计算和发送。
视频服务
成本包括带宽、硬件和功耗。
每个视频都由一个小型集群托管。每个视频由不止一台机器提供服务。
使用一个集群意味着:
提供更多内容的磁盘,带来更快的速度。
净空(Headroom)。如果一台机器出现故障,其他人可以接管。
有在线备份。
服务器使用 lighttpd 网络服务器来播放视频:
Apache 的开销太大。
使用 epoll 等待多个 fd。
从单进程切换到多进程配置以处理更多连接。
最流行的内容被移动到 CDN(内容交付网络):
CDN 在多个地方复制内容。内容接近用户的机会更大,跳数更少,内容将在更友好的网络上运行。
CDN 机器主要服务于内存不足,因为内容非常受欢迎,几乎没有内容进出内存的颠簸。
不太受欢迎的内容(每天 1-20 次观看)在各种 colo 网站中使用 YouTube 服务器。
有长尾效应。一个视频可能有一些播放,但正在播放很多视频。正在访问随机磁盘块。
在这种情况下,缓存并没有什么好处,所以花钱购买更多的缓存可能没有意义。这是一个非常有趣的观点。如果你有一个长尾产品,缓存并不总是你的性能救星。
调整 RAID 控制器,并注意其他较低级别的问题会有所助益。
调整每台机器上的内存,保证不会太多也不会太少。
服务视频要点
保持简单和便宜。
保持简单的网络路径。内容和用户之间没有太多的设备。路由器、交换机和其他设备可能无法跟上如此大的负载。
使用标准硬件。硬件越贵,其他东西也就越贵(支持合同)。您也不太可能在网上找到帮助。
使用简单的常用工具。他们使用大多数内置在 Linux 中的工具,并在这些工具之上进行分层。
处理随机搜索(SATA,tweaks)。
服务缩略图
要保证高效真地很难!
每个视频都有大约 4 个缩略图,因此缩略图比视频多得多。
缩略图仅托管在几台机器上。
服务大量小对象相关的问题:
大量磁盘查找以及操作系统级别的 inode 缓存和页面缓存问题。
遇到每个目录文件的限制。尤其是 Ext3。转移到一个更分层的结构。最近对 2.6 内核的改进可能会将 Ext3 大目录的处理能力提高100 倍,但在文件系统中存储大量文件仍然不是一个好主意。
大量 QPS,因为网页上可以显示 60 个缩略图。
在如此高的负载下,Apache 表现不佳。
在 Apache 前使用 squid(反向代理)。这工作了一段时间,但随着负载的增加,性能最终下降。从 300 个请求/秒变为 20 个。
尝试使用 lighttpd,但使用单线程时它停止了。遇到多进程模式的问题,因为它们每个都会维持一个单独的缓存。
有这么多图像,导致设置一台新机器需要 24 小时以上。
重新启动机器需要 6-10 小时让缓存预热到不访问磁盘。
为了解决他们所有的问题,他们开始使用 Google 的 BigTable,一个分布式数据存储:
避免小文件问题,因为它将文件聚集在一起。
快速、容错。假设它在不可靠的网络上工作。
较低的延迟,因为它使用分布式多级缓存。此缓存适用于不同的搭配站点。
有关 BigTable 的更多信息,请查看Google 架构、GoogleTalk 架构和BigTable。
数据库
早期
使用 MySQL 存储元数据,如用户、标签和描述。
由具有 10 个磁盘的单片 RAID 10 卷提供数据。
靠信用卡为生,所以他们租用了硬件。当他们需要更多硬件来处理负载时,需要几天时间才能订购和交付。
他们经历了一个普遍的演变:单服务器,到具有多个读从的单个主服务器,然后对数据库进行分区,然后确定分片方法。
遇到主从延迟。master 是多线程的,并且在大型机器上运行,因此它可以处理大量工作。从站是单线程的,通常在较小的机器上运行,并且复制是异步的,因此从站可能会明显落后于主站。
更新导致缓存未命中,这些缓存未命中进入磁盘,其中慢 I/O 导致慢复制。
使用复制架构,需要花费大量资金来提高写入性能。
他们的解决方案之一是通过将数据分成两个集群来优先处理流量:一个视频观看池和一个通用集群。这个想法是考虑到人们想要观看视频,因此该功能应该获得最多的资源。YouTube 的社交网络功能不太重要,所以可以将它们路由到功能较弱的集群。
晚期
使用数据库分区。
拆分成分片,用户分配到不同的分片。
传播读写。
更好的缓存局部性,这意味着更少的 IO。
实现硬件减少 30%。
将副本延迟减少到 0。
现在几乎可以任意扩展数据库。
数据中心战略
最初使用托管管理服务提供商。靠信用卡过活,所以这是唯一的办法。
托管主机无法随意扩展。无法控制硬件或制定有利的协议。
所以他们选择主机代管。现在他们可以定制一切并协商自己的合同。
使用 5 或 6 个数据中心以及 CDN。
视频来自任何数据中心。不是最接近的匹配。如果视频足够受欢迎,它将进入 CDN。
视频带宽依赖,而不是真正的延迟依赖。可以来自任何 colo。
图像延迟很重要,尤其是当页面上有 60 个图像时。
使用 BigTable 将图像复制到不同的数据中心。代码通过查看不同的指标以了解谁最接近。
经验总结
拖延时间。创造性和冒险的技巧可以帮助你在短期内应对,同时制定长期解决方案。
优先。了解对服务至关重要的内容,并围绕这些优先事项确定资源和工作的优先级。
选择你的战场。不要害怕外包一些基本服务。YouTube 使用 CDN 分发他们最受欢迎的内容。创建自己的网络将花费太长时间且成本太高。你的系统中可能有类似的机会。查看软件即服务以获得更多想法。
把事情简单化! 简单性使你可以更快地重新架构,以便对问题做出响应。确实没有人真正知道什么是简单,但如果你不害怕做出改变,那么这就是简单的一个好兆头。
分片。分片有助于隔离和约束存储、CPU、内存和 IO。这不仅仅是为了获得更多的写入性能。
在瓶颈上持久迭代:
软件:数据库、缓存
操作系统:磁盘 I/O
硬件:内存、RAID
作为一个团队成功。拥有一支了解整个系统以及系统底层内容的优秀跨学科团队。可以配置打印机、机器、安装网络等的人。有一个好的团队,一切皆有可能。
评论