from http://www.ccthere.com/alist/2357486
Flickr.com 是网上最受欢迎的照片共享网站之一,还记得那位给Windows Vista拍摄壁纸的Hamad Darwish吗?他就是将照片上传到Flickr,后而被微软看中成为Vista壁纸御用摄影师。
Flickr.com 是最初由位于温哥华的Ludicorp公司开发设计并于2004年2月正式发布的,由于大量应用了WEB 2.0技术,注重用户体验,使得其迅速获得了大量的用户,2007年11月,Flickr迎来了第20亿张照片,一年后,这个数字就达到了30亿,并且还在以加速度增长。
2005年3月,雅虎公司以3千500万美元收购了Ludicorp公司和Flickr.com。虽然Flickr并不是最大的照片共享网站(Facebook以超过100亿张照片排名第一),但这笔收购仍然被认为是WEB 2.0浪潮中最精明的收购,因为仅仅一年后,Google就以16亿美元的高价收购了YouTube,而2007年10月,微软斥资2.4亿美元收购Facebook 1.6%股份,此举使Facebook估值高达150亿美元。估计Ludicorp公司的创始人Stewart Butterfield和Caterina Fake夫妇现在还在后悔吧。[em17]
在2005年温哥华PHP协会的简报以及随后的一系列会议上,Flickr的架构师Cal Henderson公开了大部分Flickr所使用的后台技术,使得我们能有机会来分享和研究其在构建可扩展Web站点的经验。[em21] 本文大部分资料来自互联网和自己的一点点心得,欢迎大家参与讨论,要是能够起到抛砖引玉的作用,本人将不胜荣幸。
[ALIGN=CENTER]
Flickr 网站架构综述[/ALIGN]
在讨论Flickr 网站架构之前,让我们先来看一组统计数据(数据来源:April 2007 MySQL Conf and Expo和Flickr网站)
。每天多达40亿次的查询请求
。squid总计约有3500万张照片(硬盘+内存)
。squid内存中约有200万张照片
。总计有大约4亿7000万张照片,每张图片又生成不同尺寸大小的4-5份图片
。每秒38,000次Memcached请求 (Memcached总共存储了1200万对象)
。超过2 PB 存储,其中数据库12TB
。每天新增图片超过 40万(周日峰值超过200万,约1.5TB)
。超过8百50万注册用户
。超过1千万的唯一标签(tags)
你如果觉得这些过时的数据都已经很惊人了,那么让我们来看看Cal Henderson在2008年9月的一次会议上公布的另一组数据,在短短的一秒钟内:
。响应4万个照片访问请求
。处理10万个缓存操作
。运行13万个数据库查询
这张是Flickr的网站架构图,我们这里只作一些简要的描述,具体的分析请静待后续文章。
[IMGA]http://farm4.static.flickr.com/3494/3804744387_b00a875869.jpg[/IMGA]
。Pair of ServerIron's
- Load Balancer
。Squid Caches
- 反向代理,用于缓存静态的HTML和照片
。Net App'
- NetApp 公司的Filer, NAS存储设备,用于存储照片
。PHP App Servers
- 运行REDHAT LINUX,Apache上的PHP应用,Flickr网站的主体是大约6万行PHP代码
- 没有使用PHP session, 应用是stateless,便于扩展,并避免PHP Server故障所带来的Session失效。
- 每个页面有大约27~35个查询(不知道为什么这么设计,个人觉得没有必要[em06])
- 另有专门的Apache Web Farm 服务于静态文件(HTML和照片)的访问
。Storage Manager
- 运行私有的,适用于海量文件存储的Flickr File System
。Dual Tree Central Database
- MySQL 数据库,存放用户表,记录的信息是用户主键以及此用户对以的数据库Shard区,从中心用户表中查出用户数据所在位置,然后直接从目标Shard中取出数据。
- “Dual Tree"架构是”Master-Master"和“Master-Slave"的有效结合,双Master 避免了“单点故障”,Master-Slave又提高了读取速度,因为用户表的操作90%以上是读。
。Master-master shards
- MySQL 数据库,存储实际的用户数据和照片的元数据(Meta Data),每个Shard 大约40万个用户,120GB 数据。每个用户的所有数据存放在同一个shard中。
- Shard中的每一个server的负载只是其可最大负载的50%,这样在需要的时候可以Online停掉一半的server进行升级或维护而不影响系统性能。
- 为了避免跨Shard查询所带来的性能影响,一些数据有在不同的Shard有两份拷贝,比如用户对照片的评论,通过事务来保证其同步。
。Memcached Cluster
- 中间层缓存服务器,用于缓存数据库的SQL查询结果等。
。Big Search Engine
- 复制部分Shard数据(Owner’s single tag)到Search Engine Farm以响应实时的全文检索。
- 其他全文检索请求利用Yahoo的搜索引擎处理(Flickr是Yahoo旗下的公司[em07])
服务器的硬件配置:
- Intel或AMD 64位CPU,16GB RAM
- 6-disk 15K RPM RAID-10.
- 2U boxes.
服务器数量:(数据来源:April 2008 MySQL Conference & Expo)
166 DB servers, 244 web servers(不知道是否包括 squid server?), 14 Memcached servers
Flickr 网站架构研究(2) [ 西电鲁丁 ] 于:2009-08-16 21:48:57 复:2357486
[ALIGN=CENTER]
数据库最初的扩展-Replication[/ALIGN]
也许有人不相信,不过Flickr确实是从一台服务器起步的,即Apache/PHP和MySQL是运行在同一台服务器上的,很快MySQL服务器就独立了出来,成了双服务器架构。随着用户和访问量的快速增长,MySQL数据库开始承受越来越大的压力,成为应用瓶颈,导致网站应用响应速度变慢,MySQL的扩展问题就摆在了Flickr的技术团队面前。
不幸的是,在当时,他们的选择并不多。一般来说,数据库的扩展无外是两条路,Scale-Up和Scale-Out,所谓Scale-Up,简单的说就是在同一台机器内增加CPU,内存等硬件来增加数据库系统的处理能力,一般不需要修改应用程序;而Scale-Out,就是我们通常所说的数据库集群方式,即通过增加运行数据库服务器的数量来提高系统整体的能力,而应用程序则一般需要进行相应的修改。在常见的商业数据库中,Oracle具有很强的Scale-Up的能力,很早就能够支持几十个甚至数百个CPU,运行大型关键业务应用;而微软的SQL SERVER,早期受Wintel架构所限,以Scale-Out著称,但自从几年前突破了Wintel体系架构8路CPU的的限制,Scale-Up的能力一路突飞猛进,最近更是发布了SQL 2008在Windows 2008 R2版运行256个CPU核心(core)的测试结果,开始挑战Oracle的高端市场。而MySQL,直到今年4月,在最终采纳了GOOGLE公司贡献的SMP性能增强的代码后,发布了MySQL5.4后,才开始支持16路CPU的X86系统和64路CPU的CMT系统(基于Sun UltraSPARC 的系统)。
从另一方面来说,Scale-Up受软硬件体系的限制,不可能无限增加CPU和内存,相反Scale-Out却是可以"几乎"无限的扩展,以Google为例,2006年Google一共有超过45万台服务器(谁能告诉我现在他们有多少?!);而且大型SMP服务器的价格远远超过普通的双路服务器,对于很多刚刚起步或是业务增长很难预测的网站来说,不可能也没必要一次性投资购买大型的硬件设备,因而虽然Scale-Out会随着服务器数量的增多而带来管理,部署和维护的成本急剧上升,但确是大多数大型网站当然也包括Flickr的唯一选择。
经过统计,Flickr的技术人员发现,查询即SELECT语句的数量要远远大于添加,更新和
删除的数量,比例达到了大约13:1甚至更多,所以他们采用了“Master-Slave”的复制模式,即所有的“写”操作都在发生在“Master",然后”异步“复制到一台或多台“Slave"上,而所有的”读“操作都转到”Slave"上运行,这样随着“读”交易量的增加,只需增加Slave服务器就可以了。
[IMGA]http://farm4.static.flickr.com/3537/3827511075_46f2b25e17.jpg[/IMGA]
让我们来看一下应用系统应该如何修改来适应这样的架构,除了”读/写“分离外,对于”读“操作最基本的要求是:1)应用程序能够在多个”Slave“上进行负载均分;2)当一个或多个”slave"出现故障时,应用程序能自动尝试下一个“slave”,如果全部“Slave"失效,则返回错误。Flickr曾经考虑过的方案是在Web应用和”Slave“群之间加入一个硬件或软件的”Load Balancer“,如下图
[IMGA]http://farm3.static.flickr.com/2426/3827511153_4521cd291c.jpg[/IMGA]
这样的好处是应用所需的改动最小,因为对于应用来说,所有的读操作都是通过一个虚拟的Slave来进行,添加和删除“Slave"服务器对应用透明,Load Balancer 实现对各个Slave服务器状态的监控并将出现故障的Slave从可用节点列表里删除,并可以实现一些复杂的负载分担策略,比如新买的服务器处理能力要高过Slave群中其他的老机器,那么我们可以给这个机器多分配一些负载以最有效的利用资源。一个简单的利用Apache proxy_balancer_module的例子如下:
。。。。。。。。。。。。。。
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
。。。。。。。。。。。。。。。。。。。。
<Proxy balancer://mycluster>
BalancerMember "http://slave1:8008/App" loadfactor=4
BalancerMember "http://slave2:8008/App" loadfactor=3
BalancerMember "http://slave3:8008/App" loadfactor=3
....................
///slave load ratio 4:3:3.
最终,Flickr采用了一种非常“轻量”但有效的“简易”PHP实现,基本的代码只有10几行,[em21]
function db_connect($hosts, $user, $pass){
shuffle($hosts); //shuffle()是PHP函数,作用是将数组中每个元素的顺序随机打乱。
foreach($hosts as $host){
debug("Trying to connect to $host...");
$dbh = @mysql_connect($host, $user, $pass, 1);
if ($dbh){
debug("Connected to $host!");
return $dbh;
}
debug("Failed to connect to $host!");
}
debug("Failed to connect to all hosts in list - giving up!");
return 0;
}
在上述代码中,如果需要对特定的Slave赋予更高的负载,只要在$hosts中多出现一次或多次就可以了。这段代码只要稍稍改进,就可以实现更复杂的功能,如当connect失败时自动将host从hosts列表中去除等。
“Master”-"Slave"模式的缺点是它并没有对于“写'操作提供扩展能力,而且存在单点故障,即一旦Master故障,整个网站将丧失“更新”的能力。解决的办法采用“Master"-"Master"模式,即两台服务器互为”Master“-"Slave",这样不仅”读/写“能力扩展了一倍,而且有效避免了”单点故障“,结合已有的“Master"-"Slave",整个数据库的架构就变成了下面的”双树“结构,
[ALIGN=CENTER][IMGA]http://farm3.static.flickr.com/2480/3828501137_ab973b9218.jpg[/IMGA]。[/ALIGN]
“双树”架构并没有支撑太久的时间,大概6个月后,随着用户的激增,系统再一次达到了极限,不仅”写”操作成为了瓶颈,而且“异步复制"也由于”Slave“服务器过于繁忙而出现了严重的滞后而造成读数据的不一致。那么,能不能在现有架构加以解决,比如说增加新的”Master“服务器和考虑采用”同步复制“呢?答案是否定的,在Master超过两台的设置中,只能采用”闭环链“的方式进行复制,在大数据量的生产环境中,很容易造成在任意时刻没有一个Master或Slave节点是具有全部最新数据的(有点类似于”人一次也不能踏进同一条河“?[em16]),这样很难保障数据的一致性,而且一旦其中一个Master出现故障,将中断整个复制链;而对于”同步复制“,当然这是消除”复制滞后“的最好办法,不过在当时MySQL的同步复制还远没有成熟到可以运用在投产环境中。
Flickr网站的架构,需要一次大的变化来解决长期持续扩展的问题。
-----------------------------------------------------------------
以上正文预览由
SOSO博客
提供,原文地址:
http://user.qzone.qq.com/914955868/blog/1275553719