从事发布系统(web publish system)的研究和开发快两年了,从小型应用到中型应用,基本上没有参与大型应用(千万pv/day)的部署,网络上这种技术
的探讨都不是特别全面,有的提及发布系统对分布式部署,以及海量负载,有的干脆只层网络层面进行讲解,我感觉这是个系统工程,不仅要考虑到应用层面(user layer or app layer),也要考虑到系统层面(kernel layer or system layer),还要考虑到数据库
层面(database layer),否则可能有失偏颇。
我现在从三个层面就我的理解说一些我的一些看法,碍于知识和实践的局限性,也会相当有限。
所谓应用层面指的是前端应用,因为对网站来说,网友接触最多的就是前端页面,影响负载的很大程度上也是每天上千万的page view带来的visit,对web1.0的网站来说,前端页面往往都是静态化的,即html化的,这也是为了降低负载,因为web应用服务器解析 html页面的速度是最快的,而页面的静态化一般都是由web级的(主要)和桌面局域网级别的(很少)发布平台发布的,基于分布式的考虑,发布系统最好能够分发产生的html页,分发到光纤或者高速局域网中的不同host上,以便分散访问压力。当然也可以使用系统层的同步工具完成这个工作
,注意要对页面的域名对应信息进行保存,防止产生404 error。我个人比较喜欢系统层的网络同步,速度比较快,稳定性也比较高。应用层的分发一般借助ftp的方式,速度不是特别快,容易产生拥塞,稳定性自然下降。
如果分布式的分发静态页面仍然存在瓶颈,怎么办?国内大型的门户网站往往采取可缓存的反向代理方式部署的负载均衡技术来解决,一般都是squid做前端 cache和反向代理。负载均衡也有软件级的(dns 轮询)负载均衡和硬件上的负载均衡甚至两者的结合进行实现,具体实施细则将在下一篇中进行阐述。说到静态化,也不只是web1.0的传统新闻门户采用, web2.0的应用前端也可静态化,或者部分静态化,比如:社区型门户,帖子就可以静态化,可以采取即时静态或者异步静态的方式,也可以触发静态化。这种静态化可以降低数据库层的压力,数据库服务器如果始终工作在大负载的访问压力下,很容易崩溃,尽可能的将经常用到的数据静态化,缓存起来会极大的降低压力。(猫扑、网易、搜狐等社区都是采用的这种方式)
上文提到了静态化能减轻数据库服务器的压力,可是却影响了更新的即时性,有些应用需要数据的即时显示,不允许缓存或者静态化,这就需要对数据库服务器的结构进行合理部署。除了要在设计应用之初,很好的设计数据库结构,使用好的模式之外,还要对数据库服务器进行分布式部署甚至库表散列。在数据库集群 (database culuster)方面,很多数据库都有不错的解决方案,包括Oracle、Sybase甚至mysql,只不过mysql采用的是master+ slave的结构,选用了何种数据库,就参照相应的解决方案进行部署。除了在数据库选择上进行负载均衡之外,也可以在单数据库本身进行考虑,比如库表的散列,根据应用的特点,将大的、影响性能的数据库或者数据库的单表进行散列、拆分。比如:按用户id进行散列,按分类进行散列,或者按地区进行散列。
说到系统层,可能就是OS和Web Server了,大型应用的OS基本都是Unix(包括freebsd或者HP Unix等)或者类Unix(各种linux
版本,redhat居多),这不是说Microsoft的OS就不合理了,合理的应用也可部署大型应用,只不过效能会很受限制。Web Server层面,还是apache当家,尤其是静态页和图片,当然也可以根据具体的需求,根据内容的特殊性选择Lighttpd(比较适合做纯静态、图片服务器、视频服务器等)、甚至iis(windows
下用的居多),系统层的web服务器的配置还是很有讲究的,比如对cache的配置,反向代理的配置等。比较好的web加速和代理服务器有:Squid、Nginx、HAProxy、Lighttpd,这四个可能是用的比较多的了。其中业内比较出名的 Flickr、tudou用的是lighttpd,sina和51.com使用了,至少部分使用了Nginx。
缓存系统对高负载的重要性是不言而喻的,前面提到的静态化,需要进行有效缓存,经常用到的查询和结果需要进行缓存,只要设定好更新缓存的规则,对性能的提升是n个数量级的。Linux下,有内存级别的缓存,高速缓存,很多应用都是用tmpfs来进行数据中转,php上用的最多的是memcached, apache有文件系统级别的cache,squid也是做前端cache的主要手段。腾讯、网易等都是用了squid做前端cache server。
前面提到的负载均衡,有软件级别的,比如LVS、HAProxy、Linux-HA项目等,硬件层面的诸如:f5的BigIp、3DNS,alton的解决方案,北电的方案等,都是比较成熟的,不过都需要付出相当可观的¥。
以前谈到过关于高负载、大访问量的门户型web1.0网站的体系结构,提到了许多诸如front-end cache,clustered database,proxy server,cdn等技术,随着web2.0
的温度越来越high,web2.0的一些代表性网站的体系结构也被晒了出来,我在这里进行简单的整理,呈现给大家。
案例1:豆瓣
豆瓣是由阿北
(杨勃) 花4个多月时间(很神速,关键是胸有成竹),基于linux+lighttpd+fastcgi+python+quixote+mysql架构部署的 web2.0网站,豆瓣的搜索引擎使用twisted,这个是豆瓣的后台,书的价格以及比较信息都是在此之上搜索各大购物网站而来的,mysql用了 innodb和myisam两种引擎,读/写频繁的用innodb,读多写少、写多读少(比如log)或者需要full text index的用myisam,replication/cluster做数据复制和集群,晚上用mysqldump做backup。
案例2:youtube
出于开发效率的考虑,youtube的大部分代码都是python
的, web server有两种,一种是apache+fastcgi,另一种是lighttpd(主要做为视频内容服务器),youtube可能是lighttpd 最好的案例。youtube每一个视频都有4个缩略图(Thumbnails),这个缩略图的产生对服务器的负载是个极大的考验,每一秒都给disk的 i/o带来压力,youtube采用了独立的服务器culuster来应对这方面的压力,也对操作系统
和缓存做了优化。另外,缩略图的request也导致了lighttpd性能下降,通过 Hack Lighttpd 增加更多的 worker thread很大程度解决了这个问题,被google收购以后,开始使用google的存储法宝bigtable,一下子提升了在 performance、redundancy、cache等方面的表现。(看来这次收购还是效果颇大)出于redundancy的考虑,每一个 video都放到一组mini cluster上,这组mini cluster上存储了相同内容的视频,the hotest video放在了cdn上,使压力分布到不同的节点上,非热门的,访问量不高的自己进行单独处理。维护的工具也是常见的rsync(同步工具)、ssh (远程登录)等。数据库上,youtube跟很多web2.0的站点一样,偏向使用mysql,主要是存储一些meta data,诸如视频信息、图片信息、用户信息等。youtube通过删除swap交换分区来解决数据库遇到的swap颠簸问题。
youtube最初的 DB 只有 10 块硬盘,后来追加了一组 RAID1。在扩展性方面,采用的是主流的方式,master/slave复制(replication),分散IO。最终的解决之道是是业务层面的分区(在用户名字或者 ID 上做文章,应用程序控制查找机制),而不是物理上的数据库层面的表分区。youtube也用了memcached
。
案例3:myspace
myspace有6500万的订阅者(还在上升),是因特网上增长最快的网站之一,每天还有260,000新用户注册。它经常因为性能问题而受指责, MySpace不得不处理其他
网站很少碰到的或大或小的一些问题。它们是怎么做的呢? 使用的平台是 ASP.NET 2.0 + Windows + IIS + SQL
Server ,myspace 每天处理15亿的页面查看,白天处理230万并发的用户,在50万用户的时候,采用简单的磕磕绊绊的体系结构,100万用户时进行了痛苦的垂直分割解决伸缩性,300万用户时Scale-Out 胜过Scale-Up(按比例增加), 900万用户的时候,站点迁移到ASP.NET,增加了虚拟存储,260万用户的时候myspace采用了64位技术,当小于300万个帐号的时候,他们使用了一种数据库体系结构,围绕着垂直分割的概念,提供不同服务比如界面登录,用户资料和博客等的网站的各部分都有单独的数据库。垂直分割方案有助于分开数据库读和写的工作量,并且当用户需要一个新特征时,MySpace 将会加入一个新的在线数据库来支持它。MySpace 从直接使用附着于它的数据库的服务器的存储设备转换到一个存储区域网络(SAN),里面大量的磁盘存储设备由一个高速,专用网络联系到一块,同时数据库连接到SAN。到SAN的改变提高了性能,正常运行时间和可靠性。 当超过300万个帐号的时候,垂直分割解决方案就不好使了,因为它们重复了一些水平的信息像跨过所有垂直片的用户帐号。有这么多的重复它会使系统变慢,肯定要失败。个人应用比如Web 站点子部分上的博客将会增长到对于单独一个数据库服务器来说太大的程度,在逻辑上重组所有核心数据到一个数据库里
,把它的用户基本信息分成100万帐号一个的块,然后把所有有键的数据放到SQL Server不同实例的这些帐号中,在 900万-1700万帐号这个阶段,迁移到ASP.NET后,使用了比先前的体系结构更少的资源。150个服务器运行新的代码就能够做原来246个服务器做的同样的工作。再看看存储瓶颈,实施SAN解决了原来的一些性能问题,但是现在Web站点的需求开始间歇性地超过了SAN的I/O能力,它从磁盘存储读写的速度,使用每个数据库100个帐号的分开方式达到了极限,因为这已经超过了极限;迁移到一个虚拟存储体系结构,那里整个SAN被当作一个大的存储池来对待,不需要特定的磁盘为特定的应用服务。现在MySpace在设备上从相对新的SAN厂商,3PARdata方面已经标准化了。增加了一个高速缓存层,服务器放在Web服务器和数据库服务器之间,它唯一的工作就是捕获内存中频繁访问的数据对象的副本,然后把它们用于Web应用,不需要数据库查询。超过2600万注册帐号后,开始迁移到64位SQL server以解决它们的内存瓶颈问题。它们的标准数据库服务器配置使用64GB的RAM。
Myspace的经验告诉我们:你可以使用微软
的技术构建大型网站;从一开始就应该使用缓存;高速缓存是一个更好的地方存储临时数据,比如Web站点上跟踪一个特定用户的会话产生的临时文
件,就不再需要记录到数据库里;嵌入OS特征来检测拒绝服务攻击会产生无法解释的错误;把数据分布到地理位置不同的数据中心,以免发生断电事故。从开始就考虑使用虚拟存储/簇文件系统。它能让你大量并行IO访问,而且不需要任何重组就能够增加所需要的磁盘。