Browser Work | 浏览器、前端、杂记

忍受苦痛,尽善尽美。

YouTube架构简介

27 Feb 2016

YouTube以令人难以置信增涨速度达到视频日播放超亿次的规模,而负责维护网站规模的却是少数几个人。他们是如何将所有视频成功交付给所有用户的?被Google收购后他们又有了怎样的演进?

youtube

平台

  1. Apache
  2. Python
  3. Linux (SuSe)
  4. MySQL
  5. psyco,一种由Python到C的动态编译器
  6. 视频服务器使用lighttpd而非Apache

一组数据

  1. 支持日交付视频超亿次。
  2. 2005年2月创立。
  3. 2006年3月,视频日播放3000万次。
  4. 2006年7月,视频日播放1亿次。
  5. 系统管理员2名,负责平台可伸缩性的软件架构师2名
  6. 功能开发者2名,网络工程师2名,数据库管理员1名。

应对快速增涨的秘诀

while (true)
{ 
	identify_and_fix_bottlenecks();
	drink();
	sleep();
	notice_new_bottleneck();
}

此循环每天执行很多次。

Web服务器

  1. 使用NetScalar平衡负载并缓存静态内容。
  2. 通过mod_fast_cgi运行Apache。
  3. 请求经Python应用服务器路由后处理。
  4. 应用服务器与各种数据库及其他信息源通话,从而取得所有数据并格式化html页面。
  5. 通常可通过添加更多的机器来扩展web层。
  6. 通常瓶颈并不在Python的web代码,大部分时间都阻塞在RPC上。
  7. 使用Python能做到快速灵活的开发和部署。鉴于他们所面对的竞争,这是关键一环。
  8. 页面服务时间通常少于100毫秒。
  9. 使用psyco,一种Python到C的动态编译器,该编译器使用一种JIT编译方法来优化内层循环。
  10. 对于加密之类的高度处理器密集行为则使用C扩展模块。
  11. 对于渲染成本较高的块使用预生成并缓存的HTML。
  12. 数据库中的行级缓存。
  13. 将内容完整的Python对象缓存起来。
  14. 某些数据经计算后发送到每个应用,从而使数据缓存在局部存储中。这是一种未受到充分重视的策略。最快的缓存是你的应用服务器,将预先算好的数据发送到所有服务器花不了太多时间。设置一个监听变化、完成预计算并发送数据的代理就够了。

视频伺服

  • 成本包括带宽、硬件和电力。
  • 每个视频都存储在一个微型的集群上。每个视频都由多台机器伺服。
  • 使用集群意味着:
    • 更多伺服内容的磁盘,进而意味着更快的速度。
    • 冗余量。一台机器当机时其他机器可以接管。
    • 拥有在线备份。
  • 视频使用lighttpd web服务器:
    • Apache开销太大。
    • 使用epoll同时等待多个文件描述符。
    • 从单进程切换到多进程配置以处理更多连接。
  • 最流行的内容移到CDN(内容交付网络)
    • CDN将数据复制到多个位置。更有可能使内容靠近用户,级跳更少,内容也可能通过更为友好的网络传输。
    • CDN的机器常常直接从内存中伺服内容,因为内容如此流行,极少会在内外存之间颠簸。
  • 不常访问的内容(每天1到20次播放)使用各种代管网站中的YouTube服务器。
    • 长尾效应。某视频可能播放次数很少,但很多视频会被播放。会随机访问磁盘块。
    • 这种情形中缓存作用不大,因此花钱买更多缓存并无意义。这是非常有趣的一点。对于一款长尾产品,缓存未必是性能的救星。
    • 调节RAIL处理器,关注其他底层问题作为辅助。
    • 调节每台机器上的内存,避免过多或过少。

视频伺服的关键点

  1. 保持简单、便宜。
  2. 维持一条简单的网络路径。内容和客户之间的设备不要太多。路由器、交换机和其他设施很难跟得上这么高的负载。
  3. 使用商用硬件。更贵的硬件什么都跟着贵(如支持合约)。网上获得帮助的可能性也更小。
  4. 使用简单常见的工具。他们使用的工具大都是构建在Linux中以及在此基础上构造的。
  5. 处理好随机访问(SATA,tweaks)

伺服缩略图

  • 想做到高效比登天还难。
  • 每个视频约有4张缩略图,所以缩略图比视频多得多。
  • 缩略图存储在有限几台机器上。
  • 罗列一下与伺服大量小对象有关的问题:
    • 大量的磁盘寻道以及操作系统层与inode缓存和页面缓存相关的问题。
    • 遭遇单目录文件数目限制。尤其是Ext3。已改用更为层次化的结构。2.6内核中新近的改进可能将大目录容量提高100倍,然而在文件系统中存储大量文件总不是个好主意。
    • 每秒钟的请求数量很大,因为一张web页面上可以显示60张缩略图。
    • 如此高的负荷下Apache表现很差。
    • 在Apache前面使用squid(反向代理)。这可以抵挡一时,但随着负荷继续提高性能最终会降下来。从每秒钟300次请求降到20次。
    • 使用单线程的squid分层,结果抛锚。遭遇了多进程模式的问题,因为每个squid都持有单独的一份缓存。
    • 由于图片数量巨大,搭建一台新机器需要24小时。
    • 重启机器后要经过6到10小时候才能达到只读缓存不读磁盘的状态。
  • 为解决所有这些问题他们起用了Google的BigTable,一种分布式的数据存储:
    • 避免了小文件问题,因为文件都聚集在一起。
    • 快速、容错。假定它工作在不可靠的网络上。
    • 低延时,因为使用了分布式多级缓存。这种缓存可以跨不同的代管站点工作。
    • 关于BigTable的更多信息可以查阅Google架构、GoogleTalk架构和BigTable。

数据库

  1. 早期的几年:
    • 使用MySQL存储诸如用户、标签和描述之类的元数据。
    • 从具有10块磁盘的单个RAID 10 Volume上伺服数据。
    • 靠信用卡度日的岁月他们租借硬件。当需要更多硬件来处理负载时,从下订单到交付要花好几天时间。
    • 他们经历了一次常规的进化:从单台服务器到单主多从(读),然后分割数据库,再然后选定了一种分片方式。
    • 为复制延迟所困。主数据库多线程并运行在一台大机器上,因此可处理大量工作。从数据库是单线程的,运行在较小的机器上并进行异步复制,于是从库会严重滞后于主库。
    • 更新导致缓存未命中,进而读取磁盘,而磁盘上缓慢的I/O导致缓慢的复制。
    • 使用复制架构需要花大量的钱不断提高写入性能。
    • 他们的解决方案之一是将数据分成两个集群:一个视频播放池和一个一般集群,从而为流量分出优先级。其思想是:人们想要观看视频,因此这一功能应获得最多的资源。YouTube的社交网络特性则相对次要,因此可以路由到更弱的集群上。
  2. 后来的几年:
    • 转向数据库分割。
    • 分成不同的片并将用户分配到不同的片。
    • 分散读和写。
    • 更好的缓存局部性,意味着更少的IO。
    • 结果是硬件减少30%。
    • 复制延迟降低到0。
    • 现在几乎可以任意伸缩数据库。

数据中心策略

  1. 最初使用托管式主机提供商。靠信用卡度日这是唯一的办法。
  2. 托管式主机不可伸缩。你无法控制硬件,也不能签署称心的网络协议。
  3. 于是他们转向托管服务器。现在什么都能定制,也能自主协商网络协议。
  4. 使用5到6个数据中心外加CDN。
  5. 视频可能来自任何数据中心。并没有最近匹配或其他什么机制。如果一个视频足够流行,它将被移入CDN。
  6. 视频是带宽依赖的,而不是真正的延时依赖。视频可以来自任何代管站点。
  7. 对于图片,延时是个问题,特别当一个页面上有60张图片的时候。
  8. 图片通过BigTable复制到不同的数据中心。代码查看不同的指标来获知哪个最近。

经验之谈

  1. 拖延时日。创造性及有风险的技巧能在短期内帮你应付问题,趁此机会可以做出长期的解决方案。
  2. 优先次序。针对你的服务,弄清楚什么是最重要的,然后围绕着这些优先次序来配置资源和人力。
  3. 主动选择。不要怕外包一些重要的服务。YouTube使用CDN分发最流行的内容。搭建自己的网络需要太多的时间和资金。你的系统也可能蕴含类似机会。更多思路可以看看软件即服务(Software as a Service)。
  4. 保持简单!简单使你能更快速地重新架构,从而对问题做出响应。的确,没有人真正明白什么是“简单”,然而当你不担心做出变化的时候,那便是“简单”到来的明显信号。
  5. 分片。分片有助于隔离并限制存储、CPU、内存和IO。这不仅仅意味着更好的写入性能。
  6. 限制瓶颈上的迭代:
    • 软件:数据库、缓存
    • 操作系统:磁盘 I/O
    • 硬件:内存、RAID
  7. 团队为赢。组建一支良好的、理解整个系统及系统内层的跨专业团队。找到会装打印机、装机器、搭网络……的人。只要团队好,一切皆有可能。

参考

  1. Youtube Architecture
  2. Google Video

(完)

comments powered by Disqus
Fork me on GitHub