大型网站的技术挑战主要来自于庞大的用户,高并发的访问和海量的数据,任何简单的业务一旦需要处理数以P计的数据和面对数以亿计的用户,问题就会变得很棘手。大型网站架构主要就是解决这类问题。
架构选型是根据当前业务需要来的,在满足业务需求的前提下,既要有足够的扩展性也不能过度设计,每次的架构升级都是为了解决系统瓶颈而做的。
随着网站业务的发展,一台服务器逐渐不能满足需求;这时候就需要将应用和数据分离
由于:80%的业务访问都会集中在20%的数据上,所以使用缓存能够大大降低数据库或文件系统的压力,提高网站性能
单节点应用服务器总有性能瓶颈,因为单节点能够处理的连接请求有限,当并发数增加后,应用服务器就可能会成为一个网站的性能瓶颈。因此可以将应用服务器集群化,通过负载均衡处理器自动化调度服务器,将请求分发
当用户达到一定规模后,主要的性能瓶颈从应用服务器层下沉到数据库层面,由于大量的数据库请求,数据库作为单节点服务无法承受压力(读写不分离时,写操作会对并发读操作造成较大的影响),从而成为网站的性能瓶颈。目前主流的数据库都提供主从复制功能,通过配置两台数据库的主从关系,可以将一台数据库的数据同步到另一台服务器上,网站可以利用这个功能实现数据库的读写分离
CDN与反向代理的基本原理都是基于缓存,区别在于CDN是部署在网络提供商的机房,而反向代理是配置在网站的中心机房,当用户请求到反向代理服务器后,如果反向代理服务器缓存着用户的请求资源,则直接返回给用户(这只是反向代理服务器的一个功能,并不是全部,反向代理还能提高网站内部安全性和节省ip)
任何一个 单一服务都无法满足大型网站的业务需求,即:在一个大型网站中,任何一个单体的,没有集群化的组件都是不应该出现的,其一是因为单一的节点无法承受如此庞大的业务需求,其二是单一节点不满足分区容错性,若单节点服务宕机,则可能导致整个业务全部失效。
分布式数据库时网站数据库拆分的最后手段,只用在单表数据规模非常大的时候才使用。不到不得已时,网站更常用的数据库拆分手段是业务拆分,将不同业务的数据部署在不同的物理服务器上。
大型网站为了应对日益复杂的业务场景,通过使用分而治之的手段将真个网站业务拆分成不同的产品线。
业务拆分可能发生在应用服务器集群化后的任意时间节点上(不一定发生在分布式数据库之后)。
由于每一个应用系统都需要执行许多相同的业务操作,比如用户管理,session管理,那么可以将这些公用的业务提取出来,独立部署。
这时候的一个web项目里包含了网站的所有模块,一个数据库里包含了所有表。
当访问量增加时,首先遇到的瓶颈是应用服务器的连接数,tomcat的连接数不能无限增加,线程数受到计算机性能指标约束,当线程达到一定数量后,线程上下文切换就会对性能造成大量损耗,响应变慢。
这时通过横向增加web服务器的方式提升并发量,同时这样对web容器内的架构影响最小,这便是web2.0时代
这时候随着网站访问量继续增加,继续增加应用服务器数量后发现数据库成了瓶颈,而数据库的最主要的瓶颈体现在两方面:
这时,根据业务特点,如果读写比差距不大,并且对数据一致性要求不是很高的情况下,数据库可以采用主从方式进行读写分离的方案,并且引入缓存机制来抗读流量。如果读写比差距很大或者对数据一致性要求高时,就不适合用读写分离方案,需要考虑业务的垂直拆分,这时期的系统架构图如下
这时候仍然是垂直架构,所有业务集中在一个项目里。项目维护、快速迭代问题会越来越严重,单个模块的开发都需要发布整个项目,项目稳定性也受到很大挑战,这是需要考虑业务的垂直拆分,需要将一些大的模块单独拆出来,这时候的架构图如下:
这时候为了进一步提升用户体验,加速用户的网站访问速度,会使用CDN来缓存信息,用户会访问最近的CDN节点来提升访问速度。此时的架构图如下:
随着业务量增大,一些核心系统数据库单表数量达到几千万甚至亿级,这时候对该表的数据操作效率会大大降低,并且虽然有缓存来抗读的压力,但是对于大量的写操作和一些缓存miss的流量到达一定量时,单库的负荷也会到达极限,这时候需要将表拆分,一般直接采用分库分表,因为只做分表的话,单个库的连接瓶颈仍然无法解决。分库分表后的架构如下:
随着流量的进一步增大,这时候系统仍然会有瓶颈出现,以订单系统为例: 单个机房的机器是有限的,不能一直新增下去,并且基于容灾的考虑,一般采用同城双机房的方式,机房之间用专线链接,同城跨机房质检的延时在几毫秒,此时的架构图如下:
由于数据库主库只能是在一个机房,所以仍然会有一半的数据库访问是跨机房的,虽然延时只有几毫秒,但是一个调用链里的数据库访问太多后,这个延时也会积少成多。其次这个架构还是没能解决数据库连接数瓶颈问题
这是从整体层面将流量分而治之的思路。这是单元化后的机构简图如下:
从上面的架构图里能看到,流量从接入层按照路由规则(比如以用户ID来路由)路由到不同单元,每个单元内都是高内聚,包含了核心系统,数据层面的分片逻辑是与接入层路有逻辑一致,也解决了数据库连接的瓶颈问题,但是一些跨单元的调用是无法避免的,同时也有些无法拆分的业务需要放在中心单元,供所有其他单元调用。