高并发、高负载大型网站系统架构(转载)
?
一些小型的网站,用简单的html静态页面就可以实现,再配合一些图片达到美化效果。网站所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单。随着公司的成长,业务的不断拓展,功能日益丰富,用户量不断增加,数据爆炸式的增长,那种集中单一的系统架构越来越不适应发展需要。例如,我们日常使用的网上电子交易网站淘宝,每天7亿次的页面访问,其中搜索宝贝过亿次,浏览宝贝过亿次,超过40亿次的用户访问,超过6亿次的交易访问,超过6亿次的宝贝访问,超过400万笔有效交易。高峰期,每秒超过25G的流量,核心业务每秒超过4.5G的流量,每秒生成几百笔交易,8万次的用户访问,1.5万次的商品访问。淘宝总共超过22TB的宝贝图片存储,超过4亿条的在线交易记录,超过2亿的在线宝贝。那么,我们应当如何构建一个系统,满足这种高安全性、高稳定性、高并发、高负责的要求呢?
??? 大型网站,在面对大量用户访问、高并发请求方面,我们可以选择加大硬件设施投入的策略,选用多核心、具备更高运算频率、更大高速缓存的高性能CPU。加大内存带宽与容量。选择更高的转速、更大的硬盘缓存、组件磁盘阵列(RAID),若资金充裕甚至可以固态硬盘。提升网络带宽等方法来满足我们的需求;软件方面使用高性能的数据库、高效率的编程语言、还有高性能的Web容器。以上提供的解决思路可以满足一段时间的需求,但在一定程度上也意味着更大的投入,并且这样的解决思路有瓶颈,没有很好的扩展性,没法根本解决大型网站面临的高负载和高并发问题。要达到良好的系统容错性、扩展性、伸缩性,系统架构更为重要。网站的分布式系统架构是一种合适的选择,并行应用在多个处理机上运行,可以明显感到性能的提升,应用的拆分使系统具有灵活的伸缩性,因为每个处理机是自治的,一个单元或资源(软件或硬件)的故障不影响其他资源的正常功能,所以分布式系统更加可靠。
??? 网站相关的技术经过这些年的发展,已经细分到很细的方方面面,尤其对于大型网站来说,所采用的技术更是涉及面非常广,从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求,已经不是原来简单的html静态网站所能比拟的。下面我从HTML静态化、应用拆分、数据库、数据储存、缓存、镜像等角度来说说大型网站的分布式架构。
??? 1、HTML静态化
??? 其实大家都知道,效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能在一些交互应用较少的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理、权限管理、自动抓取等功能,对于一个大型网站来说,拥有一套高效、可管理的CMS是必不可少的。同时,html静态化也是某些缓存策略使用的手段,对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用html静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求。
??? 二、?应用拆分
?首先,在说明应用拆分之前,我们先来回顾一下一个系统从小变大的过程中遇到的一些问题,通过这些问题我们会发现拆分对于构建一个大型系统是如何的重要。
?系统刚上线初期,用户数并不多,所有的逻辑也许都是放在一个系统中的,所有逻辑跑到一个进程或者一个应用当中,这个时候因为比较用户少,系统访问量低,因此将全部的逻辑都放在一个应用未尝不可。但是好景不长,随着系统用户的不断增加,系统的访问压力越来越多,同时随着系统发展,为了满足用户的需求,原有的系统需要增加新的功能进来,系统变得越来越复杂的时候,我们会发现系统变得越来越难维护,难扩展,同时系统伸缩性和可用性也会受到影响。那么这个时候我们如何解决这些问题呢?明智的办法就是拆分,我们需要将原来的系统根据一定的标准,比如业务相关性等分为不同的子系统,不同的系统负责不同的功能,这样切分以后,我们可以对单独的子系统进行扩展和维护,从而提高系统的扩展性和可维护性,同时我们系统的水平伸缩性大大的提升了,因为我们可以有针对性的对压力大的子系统进行水平扩展而不会影响到其它的子系统,而不会像拆分以前,每次系统压力变大的时候,我们都需要对整个大系统进行伸缩,而这样的成本是比较大的,另外经过切分,子系统与子系统之间的耦合减低了,当某个子系统暂时不可用的时候,整体系统还是可用的,从而整体系统的可用性也大大增强了。
?因此一个大型的互联网应用,肯定是要经过拆分,因为只有拆分了,系统的扩展性,维护性,伸缩性,可用性才会变的更好。但是拆分也给系统带来了问题,就是子系统之间如何通信的问题,系统之间的依赖关系。因为系统多了,系统的依赖关系就会变得复杂,此时就需要更好的去关注拆分标准,比如能否将一些有依赖的模块尽量地高内聚度、低耦合度,同时一定要注意系统之间的循环依赖,如果出现循环依赖一定要小心,因为这可能导致系统连锁启动失败。既然明白了拆分的重要性,我们看看随着淘宝的发展,淘宝本身是如何拆分系统的。淘宝对整个系统进行了水平和垂直两个方向的拆分,水平方向上,按照功能分为交易,评价,用户,商品等系统,同样垂直方向上,划分为业务系统,核心业务系统以及以及基础服务,这样以来,各个系统都可以独立维护和独立的进行水平伸缩,比如交易系统可以在不影响其它系统的情况下独立的进行水平伸缩以及功能扩展。
??? 三?、数据库拆分
???????在前面“应用拆分”主题中,我们提到了一个大型互联网应用需要进行良好的拆分,而那里我们仅仅说了”应用级别”的拆分,其实我们的互联网应用除了应用级别的拆分以外,还有另外一个很重要的层面就是存储如何拆分的。因此这个主题主要涉及到如何对数据库存储系统进行拆分。
??? 大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
??? 在数据库集群方面,很多数据库都有自己的解决方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是类似的方案,您使用了什么样的DB,就参考相应的解决方案来实施即可。数据库集群由于在架构、成本、扩张性方面都会受到所采用DB类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案。
??? 库表散列一般有两种方法:垂直扩展与水平扩展。垂直扩展:垂直扩展比较好理解,简单来说就是按照功能切分数据库,将不同功能的数据,存储在不同的数据库中,这样一个大数据库就被切分成多个小数据库,从而达到了数据库的扩展。一个架构设计良好的应用系统,其总体功能一般肯定是由很多个松耦合的功能模块所组成的,而每一个功能模块所需要的数据对应到数据库中就是一张或多张表。各个功能模块之间交互越少,越统一,系统的耦合度越低,这样的系统就越容易实现垂直切分。水平扩展:简单来说,可以将数据的水平切分理解为按照数据行来切分,就是将表中的某些行切分到一个数据库中,而另外的某些行又切分到其他的数据库中。为了能够比较容易地判断各行数据切分到了哪个数据库中,切分总是需要按照某种特定的规则来进行的,如按照某个数字字段的范围,某个时间类型字段的范围,或者某个字段的hash值。
我们在应用中按功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户ID进行表散列,这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu的论坛就是采用了这样的架构,将论坛的用户、设置、帖子等信息进行数据库分离,然后对帖子、用户按照板块和ID进行散列数据库和表,最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。
??? 四、分布式存储
数据库进行存储的数据即称为结构化数据,?在一个大型的互联网应用当中,我们会发现并不是所有的数据都是结构化的,比如一些配置文件,一个用户对应的动态,以及一次交易的快照等信息,这些信息一般不适合保存到RDBMS中,另外一些静态文件,比如各个商品的图片,商品描述等信息,这些信息因为比较大,放入RDBMS会引起读取性能问题,从而影响到其它的数据读取性能,因此这些信息也需要和其它信息分开存储,而一般的互联网应用系统都会选择把这些信息保存到分布式文件系统中,这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不会因为图片问题而崩溃,保证更高的系统消耗和执行效率。
分布式文件系统是实现非结构化数据存储的主要技术,说到分布式文件系统就不得不提GFS(全称为"Google File System"),GFS的系统架构图如下图所示。
图1:Google-file-system架构图
?
??
图2:Google-file-system架构图(详细)
?
??
?
GFS将整个系统分为三类角色:Client(客户端)、Master(主服务器)、Chunk Server(数据块服务器)。
Client(客户端):是GFS提供给应用程序的访问接口,它是一组专用接口,不遵守POSIX规范,以库文件的形式提供。应用程序直接调用这些库函数,并与该库链接在一起。
Master(主服务器):是GFS的管理节点,主要存储与数据文件相关的元数据,而不是Chunk(数据块)。元数据包括:命名空间(Name Space),也就是整个文件系统的目录结构,一个能将64位标签映射到数据块的位置及其组成文件的表格,Chunk副本位置信息和哪个进程正在读写特定的数据块等。还有Master节点会周期性地接收从每个Chunk节点来的更新("Heart- beat")来让元数据保持最新状态。
Chunk Server(数据块服务器):负责具体的存储工作,用来存储Chunk。GFS将文件按照固定大小进行分块,默认是64MB,每一块称为一个Chunk(数据块),每一个Chunk以Block为单位进行划分,大小为64KB,每个Chunk有一个唯一的64位标签。GFS采用副本的方式实现容错,每一个Chunk有多个存储副本(默认为三个)。 Chunk Server的个数可有有多个,它的数目直接决定了GFS的规模。
??? GFS之所以重要的原因在于,在Google公布了GFS论文之后,许多开源组织基于GFS的论文开发了各自的分布式文件系统,其中比较知名的有HDFS,MooseFS,MogileFS等。
??? 5、镜像
镜像网站是将一个完全相同的站点放到几个服务器,分别有自己的URL,在这些服务器上互为镜像网站。它和主站并没有太大差别,或者可算是为主站作的后备措施。有了镜像网站的好处是:如果不能对主站作正常访问(如某个服务器死掉或出了意外),但仍能通过其它服务器正常浏览。相对来说主站在速度等各方面比镜像站点略胜一筹。?
网站镜像就是网站的复制版本。因为网站是由很多网页组成的,将其中的一部分网页按原来的结构复制出来,就是一份镜像。比如,新浪在全国各地就有很多的镜像,他们和主站的版式,结构,功能都一样,只是在不同的服务器上而已。一般是个人网站的站长为自己的站做一个备份,也就是说,一个站由于流量或其它原因访问不到时, 人们可以去其他一个一模一样的站看。 这个站还可以起到分流,减少服务器压力的作用。不过,这些都是由于个人网站的服务器不能接受太多的访问量而采取的办法。 商业网站一般不用这样的办法。因为用户要记两个域名,内容要上传两次,要随时保持两个地方一致,内容一多非常麻烦。?
如果是别人把自己的站也这样原样做一份放在网上,我在想,网站的主人肯定是不能容忍的,可以用搜索引擎找到这样的站, 现在这样搞的人已经比较少了,以前我们经常会发现有人这样照抄别人的网站。所以,那时候很多网站都加了一句严禁建立镜像。
??? 镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异,比如ChinaNet和EduNet之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新。在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路,比如Linux上的rsync等工具。
??? 6、负载均衡
??? 负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,其中有两个架构可以给大家做参考。
??? 硬件四层交换,第四层交换使用第三层和第四层信息包的报头信息,根据应用区间识别业务流,将整个区间段的业务流分配到合适的应用服务器进行处理。 第四层交换功能就象是虚IP,指向物理服务器。
??? 它传输的业务服从的协议多种多样,有HTTP、FTP、NFS、Telnet或其他协议。这些业务在物理服务器基础上,需要复杂的载量平衡算法。在IP世界,业务类型由终端TCP或UDP端口地址来决定,在第四层交换中的应用区间则由源端和终端IP地址、TCP和UDP端口共同决定。在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了。
??? 软件四层交换,大家知道了硬件四层交换机的原理后,基于OSI模型来实现的软件四层交换也就应运而生,这样的解决方案实现的原理一致,不过性能稍差。但是满足一定量的压力还是游刃有余的,有人说软件实现方式其实更灵活,处理能力完全看你配置的熟悉能力。软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满足多种应用需求,这对于分布式的系统来说必不可少。
? ??一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建系统,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性,随时往架构里面增减节点都非常容易。