架构的演进

来源

大型网站的技术挑战主要来自于庞大的用户,高并发的访问和海量的数据,任何简单的业务一旦需要处理数以P计的数据和面对数以亿计的用户,问题就会变得很棘手。大型网站架构主要就是解决这类问题。
架构选型是根据当前业务需要来的,在满足业务需求的前提下,既要有足够的扩展性也不能过度设计,每次的架构升级都是为了解决系统瓶颈而做的。

过程

初始阶段

初始阶段的应用和数据通常在同一个服务器上、
arch-x-ev-g-1.png

服务与数据分离

随着网站业务的发展,一台服务器逐渐不能满足需求;这时候就需要将应用和数据分离arch-x-ev-g-2.png

使用缓存提高性能

由于:80%的业务访问都会集中在20%的数据上,所以使用缓存能够大大降低数据库或文件系统的压力,提高网站性能
arch-x-ev-g-3.png

应用服务器集群化

单节点应用服务器总有性能瓶颈,因为单节点能够处理的连接请求有限,当并发数增加后,应用服务器就可能会成为一个网站的性能瓶颈。因此可以将应用服务器集群化,通过负载均衡处理器自动化调度服务器,将请求分发arch-x-ev-g-4.png

数据库读写分离

当用户达到一定规模后,主要的性能瓶颈从应用服务器层下沉到数据库层面,由于大量的数据库请求,数据库作为单节点服务无法承受压力(读写不分离时,写操作会对并发读操作造成较大的影响),从而成为网站的性能瓶颈。目前主流的数据库都提供主从复制功能,通过配置两台数据库的主从关系,可以将一台数据库的数据同步到另一台服务器上,网站可以利用这个功能实现数据库的读写分离arch-x-ev-g-5.png

使用CDN与反向代理加强网站响应效率

CDN与反向代理的基本原理都是基于缓存,区别在于CDN是部署在网络提供商的机房,而反向代理是配置在网站的中心机房,当用户请求到反向代理服务器后,如果反向代理服务器缓存着用户的请求资源,则直接返回给用户(这只是反向代理服务器的一个功能,并不是全部,反向代理还能提高网站内部安全性和节省ip)arch-x-ev-g-6.png

分布式文件系统及分布式数据库系统

任何一个 单一服务都无法满足大型网站的业务需求,即:在一个大型网站中,任何一个单体的,没有集群化的组件都是不应该出现的,其一是因为单一的节点无法承受如此庞大的业务需求,其二是单一节点不满足分区容错性,若单节点服务宕机,则可能导致整个业务全部失效。
分布式数据库时网站数据库拆分的最后手段,只用在单表数据规模非常大的时候才使用。不到不得已时,网站更常用的数据库拆分手段是业务拆分,将不同业务的数据部署在不同的物理服务器上。

arch-x-ev-g-7.png

image.png

业务拆分

大型网站为了应对日益复杂的业务场景,通过使用分而治之的手段将真个网站业务拆分成不同的产品线。
业务拆分可能发生在应用服务器集群化后的任意时间节点上(不一定发生在分布式数据库之后)。arch-x-ev-g-9.png

分布式服务

由于每一个应用系统都需要执行许多相同的业务操作,比如用户管理,session管理,那么可以将这些公用的业务提取出来,独立部署。arch-x-ev-g-10.png

示例:电商网站架构演进

1.0时代

arch-x-ev-d-1.png
这时候的一个web项目里包含了网站的所有模块,一个数据库里包含了所有表。
当访问量增加时,首先遇到的瓶颈是应用服务器的连接数,tomcat的连接数不能无限增加,线程数受到计算机性能指标约束,当线程达到一定数量后,线程上下文切换就会对性能造成大量损耗,响应变慢。
这时通过横向增加web服务器的方式提升并发量,同时这样对web容器内的架构影响最小,这便是web2.0时代

2.0时代

arch-x-ev-d-2.png
这时候随着网站访问量继续增加,继续增加应用服务器数量后发现数据库成了瓶颈,而数据库的最主要的瓶颈体现在两方面:

  • 数据库的最大连接数是有限的,比如当前数据库的连接数设置8000,如果每个应用服务器与数据库的初始连接数设置40,那么200台web服务器是极限, 并且连接数太多后,数据库的读写压力增大,耗时增加
  • 当单表数量过大时,对该表的操作耗时会增加,索引优化也是缓兵之计

这时,根据业务特点,如果读写比差距不大,并且对数据一致性要求不是很高的情况下,数据库可以采用主从方式进行读写分离的方案,并且引入缓存机制来抗读流量。如果读写比差距很大或者对数据一致性要求高时,就不适合用读写分离方案,需要考虑业务的垂直拆分,这时期的系统架构图如下

3.0时代

读写分离arch-x-ev-d-3.png

这时候仍然是垂直架构,所有业务集中在一个项目里。项目维护、快速迭代问题会越来越严重,单个模块的开发都需要发布整个项目,项目稳定性也受到很大挑战,这是需要考虑业务的垂直拆分,需要将一些大的模块单独拆出来,这时候的架构图如下:

4.0时代

业务垂直划分arch-x-ev-d-4.png

这时候为了进一步提升用户体验,加速用户的网站访问速度,会使用CDN来缓存信息,用户会访问最近的CDN节点来提升访问速度。此时的架构图如下:

使用CDN缓存arch-x-ev-d-5.png

随着业务量增大,一些核心系统数据库单表数量达到几千万甚至亿级,这时候对该表的数据操作效率会大大降低,并且虽然有缓存来抗读的压力,但是对于大量的写操作和一些缓存miss的流量到达一定量时,单库的负荷也会到达极限,这时候需要将表拆分,一般直接采用分库分表,因为只做分表的话,单个库的连接瓶颈仍然无法解决。分库分表后的架构如下:

分库分表arch-x-ev-d-6.png



随着流量的进一步增大,这时候系统仍然会有瓶颈出现,以订单系统为例: 单个机房的机器是有限的,不能一直新增下去,并且基于容灾的考虑,一般采用同城双机房的方式,机房之间用专线链接,同城跨机房质检的延时在几毫秒,此时的架构图如下:

同城双机房
arch-x-ev-d-7.png

由于数据库主库只能是在一个机房,所以仍然会有一半的数据库访问是跨机房的,虽然延时只有几毫秒,但是一个调用链里的数据库访问太多后,这个延时也会积少成多。其次这个架构还是没能解决数据库连接数瓶颈问题

  • 随着应用服务器的增加,虽然是分库分表,但每增加一台应用服务器,都会与每个分库建立连接,比如数据库连接池默认连接数是40,而如果mysql数据库的最大连接数是8000的话,那么200台应用服务器就是极限。
  • 当应用的量级太大后,单个城市的机器、电、带宽等资源无法满足业务的持续增长。这时就需要考虑SET化架构,也就是单元化架构,大体思路就是将一些核心系统拆成多个中心,每个中心成为一个单元,流量会按照一定的规则分配给每个单元,这样每个单元只负责处理自己的流量就可以了。每个单元要尽量自包含、高内聚。

这是从整体层面将流量分而治之的思路。这是单元化后的机构简图如下:

5.0 单元化

arch-x-ev-d-8.png



从上面的架构图里能看到,流量从接入层按照路由规则(比如以用户ID来路由)路由到不同单元,每个单元内都是高内聚,包含了核心系统,数据层面的分片逻辑是与接入层路有逻辑一致,也解决了数据库连接的瓶颈问题,但是一些跨单元的调用是无法避免的,同时也有些无法拆分的业务需要放在中心单元,供所有其他单元调用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值