YouTube正在快速增长,每天的视频浏览量超过1亿次,但只有少数人维护该网站并确保可扩展性。这类似于PlentyOfFish,几个人维护一个庞大的系统。是什么原因?放心,这绝对不取决于性格或孤独。我们先来看看YouTube的整体技术架构。
平台
阿帕奇
Python
Linux(SuSe)
MySQL
psyco,动态Python到C编译器
lighttpd取代Apache进行视频观看/strong
状态
支持每日超过1亿次视频观看
2005年2月成立
2006年3月,每日视频观看次数达到3000万次
2006年7月,日均视频浏览量达到1亿次
2名系统管理员、2名可扩展性软件架构师
软件开发工程师2名、网络工程师2名、DBA/strong1名
网络服务器
1、NetScaler用于负载均衡和静态内容缓存
2.使用mod_fast_cgi运行Apache
3.使用Python应用服务器处理请求路由
4、应用服务器与多个数据库等信息源交互,获取数据并格式化HTML页面
5、一般来说,Web层的可扩展性可以通过增加更多的机器来提高。
6.Python的Web层代码通常不是性能瓶颈,大部分时间都阻塞在RPC中。
7.Python允许快速灵活的开发和部署
8.通常每个页面的服务时间不到100毫秒
9.使用psyco(一个类似于JIT编译器的动态Python到C编译器)来优化内循环
10.对于加密等密集型CPU活动,请使用C扩展
11.对一些昂贵的块使用预先生成和缓存的HTML。
12.在数据库中使用行级缓存
13.缓存完整的Python对象
14.一些数据被计算并发送到各个程序,因此这些值被缓存在本地内存中。这是一个使用不当的策略。
应用程序服务器中最快的缓存可以在很短的时间内将预先计算的值发送到所有服务器。只需获取一个代理来侦听更改、预计算并发送即可。
视频服务
1.成本包括带宽、硬件和能耗
2.每个视频由一个迷你集群托管,每个视频由多个机器托管。
3.使用集群意味着:
-更多的驱动器来保存内容意味着更快的速度
-故障转移。如果一台机器出现故障,其他机器可以继续服务
-在线备份
4.使用lighttpd作为Web服务器提供视频服务:
-阿帕奇太贵了
-使用epoll等待多个fd
-从单进程配置转移到多进程配置以处理更多连接
5.最受欢迎的内容移至CDN:
-CDN多地备份内容,内容更贴近用户的机会更高
-CDN机器经常会出现内存不足的情况,因为内容非常受欢迎,内存进出内容几乎没有变化
6.不太受欢迎的内容(每天1-20次浏览)在许多托管网站上使用YouTube服务器
-长尾效应。一个视频可以多次播放,但同时播放的视频数量较多。随机访问硬盘块
-在这种情况下,缓存效果不会很好,因此花钱购买更多缓存可能没有多大意义。
-调整RAID控制并注意其他低级问题
-调整每台机器上的内存,不要太多也不要太少/strong
视频服务要点
1.保持简单和便宜
2.保持网络路径简单,内容和用户之间不要有太多设备。
3.使用通用硬件。很难找到昂贵硬件的帮助文档。
4.使用简单通用的工具,使用Linux内置或Linux上的大部分工具
5.很好地处理随机搜索(SATA,调整)
缩略图服务
1.保持高效是极其困难的
2.每个视频大约有4个缩略图,因此缩略图比视频多很多。
3.缩略图仅托管在少数计算机上。
4、拿一些小东西时遇到的问题:
-操作系统级别的大量硬盘查找以及索引节点和页面缓存问题
-单目录文件限制,特别是Ext3,后来转移到多层结构。内核2.6的最新改进可能允许Ext3允许大型目录,但在一个文件系统中存储大量文件并不是一个好主意
-每秒大量请求,因为网页可能会在页面上显示60个缩略图
-Apache在如此高的负载下表现非常差
-在Apache前端使用squid,这工作了一段时间,但随着负载不断增加而以失败告终。它将每秒300个请求变成20个
-尝试使用lighttpd,但由于使用单线程而卡住。遇到多个进程的问题,因为每个进程都维护自己单独的缓存
-图片太多,一台新机只能拍24小时以上
-重启机器需要6-10小时才能缓存
5.为了解决所有这些问题,YouTube开始使用Google的BigTable,一种分布式数据存储:
-将文件收集在一起时避免小文件问题
-快速、容错
-较低的延迟,因为它使用可与多个不同的并置站点配合使用的分布式多级缓存
-更多信息请参考GoogleArchitecture、GoogleTalkArchitecture和BigTable
数据库
1.早期阶段
-使用MySQL存储用户、标签和描述等元数据
-使用整个10块硬盘的RAID10来存储数据
-依赖信用卡,因此YouTube租用硬件
-YouTube经历了一场共同的革命:单服务器,然后单主多读从,然后数据库分区,然后分片。
-备份延迟令人痛苦。主数据库是多线程的,运行在大型机器上,因此可以处理大量工作。从属服务器是单线程的,通常运行在较小的服务器上,并且备份是异步的,因此从属服务器将远远落后于主服务器。
-更新导致缓存故障,硬盘I/O速度慢导致备份速度慢
-使用备份架构需要花费大量资金才能获得更高的写入性能
-YouTube的一种解决方案是将数据分为两个集群来确定传输的优先级:视频观看池和通用集群
2.后期
-数据库分区
-分为分片,不同的用户分配到不同的分片
-扩散阅读和写作
-更好的缓存位置意味着更少的IO
-硬件减少30%
-备份延迟减少至0
-您现在可以任意增加数据库的可扩展性
数据中心战略
1.取决于信用卡,因此最初只能使用托管提供商
2.托管提供商不提供可扩展性、控制硬件或使用良好的网络协议
3.YouTube改用托管安排。现在YouTube可以定制一切并协商自己的合同
4.使用5到6个数据中心加CDN
5.该视频来自任意数据中心,而不是最近的比赛或其他任何内容。如果视频足够受欢迎,请将其移至CDN
6.依赖于视频带宽而不是真正的延迟。可以来自任何颜色
7、图片延迟很严重,尤其是一页有60张图片时
8.使用BigTable将图片备份到不同的数据中心,用代码看看谁最接近
关于可扩展性的思考
尽管以下想法并不新鲜,但希望对您有所帮助。
分而治之是可扩展技术的灵魂。考虑以分层方式完成所有工作。这也是数据分片的关键。了解如何对数据进行分区以及如何关联分区数据。总而言之,保持事情简单和松散耦合至关重要。
充分利用Python的动态特性构建易于扩展的软件架构。
近似正确性。相信监控系统报告的系统运行状态。如果没有出现问题,则假设一切正常。
数据模型不一致。例如,读评论的人和写评论的人对你刷新页面的动作会有不同的反应,但没有必要完全基于事务处理来设计系统,那样就大材小用了。我们仍然需要不一致的数据模型。
分布式系统中的随机性。分布式系统就像天气系统一样。调试分布式系统时会有更多的随机性。例如,缓存过期。通常,服务器会缓存热门视频24小时。如果缓存同时过期,服务器也会同时启动缓存,负载将如雷霆万钧!
最快的函数调用是不进行任何调用的函数调用。合理设计交易处理的间隔和频率。
仔细观察API并注意它。如何定义输入和输出?所有函数调用本质上都是围绕数据发生的,那么函数调用之后会发生什么呢?
在Python中使用RPC重定向。程序员是代码的构建者,因此他们需要制定约定。如果代码不幸失败,您还可以从RPC输出中追踪原因。
不存在完美的组件。组件的运行周期可能持续1至6个月。没有人知道这需要多长时间。随着时间的推移,我们将用Python和C重写东西,这证明你正在淘汰旧组件,当你看到新组件出现时,它就诞生了。
没有人了解整个系统是如何运作的。因此,我们需要定义组件。视频转码与视频搜索完全不同,建立良好的数据规范很重要。
效率和可扩展性并重。最有效的方法是用C实现该过程,但这种方法缺乏可扩展性。
着眼于宏观层面、组成部分以及它们失败的原因。使用RPC是否明智?内联怎么样?进行细分,您可能会发现差异。
注意算法。与其绞尽脑汁用Python实现高效的算法,不如用它来做一些更实际的事情。在这方面,C语言有它的优势。
我们很少从事面向对象的设计。我们使用大量的命名空间、类来组织数据,但很少使用面向对象。
我想用以下的话来描述我们的代码树:简单、实用、优雅、正交、可组合。这是我们的追求。
总结
YouTube解决问题的理念只有一个词:简单。YouTube的许多产品都是从简单的Python脚本开始的。这正应了我们的古话,不积跬步,无以至千里;不积跬步,无以至千里;不积小流,不成江河。