架构06- 理解架构的演进示例

具体以电商网站为举例, 展示web应用的架构演变过程。

web1.0时代

架构06- 理解架构的演进示例_第1张图片

在一个包含所有模块的Web项目中,当网站的访问量增加时,首先会遇到的瓶颈是应用服务器的连接数。例如,在使用Tomcat作为应用服务器时,连接数是有限制的,线程数受限于进程内存大小、CPU内核数等因素。当线程数达到一定数量时,线程上下文的切换会对性能产生严重的影响,导致响应变慢。为了解决这个问题,可以采取增加Web应用服务器的方式进行横向扩展。这意味着添加更多的应用服务器来分担负载,以提高系统的承载能力。通过这种方式可以减少单个服务器上的连接数和线程数,从而减轻并发压力,保持系统的稳定性和响应速度。此时会演变成下图

web2.0时代

架构06- 理解架构的演进示例_第2张图片

随着网站访问量的不断增加,在继续增加应用服务器数量后,发现数据库成为了新的瓶颈。数据库的瓶颈主要体现在两个方面:

1. 数据库的最大连接数是有限的。例如,当前数据库的最大连接数设置为8000,如果每个应用服务器与数据库建立的初始连接数设置为40,那么最多只能支持200台Web服务器的连接。当连接数过多时,数据库的读写压力会增大,导致耗时增加。

2. 单表数据量过大时的操作耗时增加。对于包含大量数据的单个表进行操作时,操作的执行时间会随着数据量的增加而增加。在这种情况下,可以考虑进行索引优化来加速查询操作。同时,引入缓存机制可以有效抗击读取流量,提高系统的读取性能。

针对业务特点,如果读写比例差距不大,并且对数据一致性的要求不是非常高,可以考虑采用主从复制方式实现数据库的读写分离。也就是将主数据库用于处理写操作,从数据库用于处理读操作。通过这种方式可以提高系统的并发读取能力。同时,引入缓存机制可以进一步减轻数据库的负载。然而,如果读写比例差距很大或者对数据一致性的要求非常高时,采用读写分离方案可能不太适合。这时需要考虑进行业务的垂直拆分,将不同的业务模块拆分为独立的数据库实例,以减少单个数据库的负载压力。这种方式通过将数据按照业务功能进行划分,使得每个数据库只负责特定的业务领域,从而提高系统的扩展性和性能。当应用服务器数量增加后,数据库成为了新的瓶颈。针对这个问题,可以通过采用读写分离和缓存机制来抗击读取流量,提高数据库的性能。对于读写比例差距大或对数据一致性要求高的情况,可以考虑进行业务的垂直拆分,以减轻单个数据库的负载压力,实现系统的可扩展性。演变如下

web3.0读写分离时代:

架构06- 理解架构的演进示例_第3张图片

在当前的垂直架构中,所有的业务都集中在一个项目中。然而,随着项目的维护和快速迭代,问题会变得越来越严重。每个单独模块的开发都需要发布整个项目,这不仅增加了开发的复杂性,还影响了项目的稳定性。为了解决这个问题,需要考虑进行业务的垂直拆分,将一些较大的模块从整个项目中单独拆分出来。这样做的好处是可以实现模块之间的解耦,提高开发和维护的效率。同时,将不同的业务模块拆分成独立的项目可以使团队更专注于特定领域的开发,提高开发效率和项目的稳定性。在新的架构图中,每个拆分出来的模块都成为一个独立的项目,可以有自己的开发团队和资源。这样每个模块的开发、测试和发布都可以 ** 进行,减少了对整个项目的依赖。同时,模块之间可以通过定义清晰的接口协议来进行通信和协作,实现解耦和灵活性。总结来说,针对当前垂直架构中项目维护和快速迭代问题的严重性,需要考虑进行业务的垂直拆分,将一些大的模块单独拆出来。这样可以提高开发和维护的效率,减轻团队的工作负担,同时提升项目的稳定性和可扩展性。在新的架构中,每个拆分出来的模块成为一个独立的项目,并通过定义清晰的接口协议来实现模块之间的通信和协作。

4.0业务垂直拆分:

架构06- 理解架构的演进示例_第4张图片

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

4.1使用CDN存储信息:

架构06- 理解架构的演进示例_第5张图片

当核心系统的数据库中某个表的数据量达到几千万甚至亿级时,数据操作效率会显著降低。尽管有缓存来缓解读操作的压力,但是在大量写操作以及缓存未命中的情况下,单个数据库的负荷会达到极限。为了应对这种情况,可以采用分库分表的方式进行架构调整。在分库分表的架构中,核心系统的数据库将被拆分成多个数据库(分库),每个数据库中包含一部分表(分表)。拆分后的每个独立的数据库可以通过水平扩展的方式来处理更多的负载。此外,每个表也会根据一定的规则被拆分为多个子表,从而使得每个子表的数据量更小,提高数据操作效率。在新的架构中,对于查询操作,需要根据业务逻辑确定查询需要涉及哪些表,然后在相应的分库分表中进行查询。对于写操作,同样需要进行路由,确定写操作应该落在哪个分库的哪个分表中。分库分表的架构能够有效地应对核心系统数据库单表数据量过大的问题。通过将数据库拆分成多个独立的数据库和表的组合,可以实现更好的负载均衡和提高数据操作效率。这样的架构调整可以进一步提升系统的性能和可扩展性。

4.2分库分表架构:

当核心系统的数据库中某个表的数据量达到几千万甚至亿级时,数据操作效率会显著降低。尽管有缓存来缓解读操作的压力,但是在大量写操作以及缓存未命中的情况下,单个数据库的负荷会达到极限。为了应对这种情况,可以采用分库分表的方式进行架构调整。在分库分表的架构中,核心系统的数据库将被拆分成多个数据库(分库),每个数据库中包含一部分表(分表)。拆分后的每个独立的数据库可以通过水平扩展的方式来处理更多的负载。此外,每个表也会根据一定的规则被拆分为多个子表,从而使得每个子表的数据量更小,提高数据操作效率。在新的架构中,对于查询操作,需要根据业务逻辑确定查询需要涉及哪些表,然后在相应的分库分表中进行查询。对于写操作,同样需要进行路由,确定写操作应该落在哪个分库的哪个分表中。分库分表的架构能够有效地应对核心系统数据库单表数据量过大的问题。通过将数据库拆分成多个独立的数据库和表的组合,可以实现更好的负载均衡和提高数据操作效率。这样的架构调整可以进一步提升系统的性能和可扩展性。

架构06- 理解架构的演进示例_第6张图片

当系统流量继续增大时,单个机房的机器数量有限,无法无限制地进行扩展。此外,为了保证系统的容灾性能,一般采用同城双机房的架构,通过专线将两个机房连接起来。在同城跨机房的情况下,质检的延时通常在几毫秒级别。以订单系统为例,根据上述需求和考虑,系统的架构图如下:

架构06- 理解架构的演进示例_第7张图片

在该架构中,订单系统被部署在两个机房A和B中,并通过同城专线进行连接。流量管理器用于控制流量的分发和调度,确保请求能够合理地分布到不同的机房。同时,在每个机房内部还会有负载均衡器来进一步分发请求到具体的服务器上,实现负载均衡和高可用性。通过这样的架构设计,系统可以充分利用多个机房的资源进行水平扩展,提高系统的并发处理能力和可用性。同时,同城机房之间的专线连接可以保证数据的实时同步和容灾备份。这样的架构能够更好地应对流量增长和故障恢复的需求,提高系统的稳定性和性能。

5.0单元化

架构06- 理解架构的演进示例_第8张图片

根据上述架构图,可以看出系统的接入层会按照一定的路由规则(比如以用户ID来路由)将流量路由到不同的单元。每个单元内部都包含了核心系统,并且在数据层面上采用了分片的逻辑,与接入层的路由逻辑保持一致。这样的设计解决了数据库连接的瓶颈问题。然而,一些跨单元的调用是无法避免的。有些业务逻辑是无法拆分的,需要放在中心单元中,并供所有其他单元进行调用。系统中的接入层根据特定的规则将流量路由到不同的单元,这些单元内部具有高内聚性,包含核心系统和分片逻辑,以解决数据库连接的瓶颈问题。但是,由于业务的特殊性,一些跨单元的调用是无法避免的,并且一些不可拆分的业务逻辑需要放在中心单元供其他单元进行调用。这样的设计能够更好地支持系统的扩展和分布式处理,提高系统的性能和可用性。

关注公众号:领取架构师面试资料

你可能感兴趣的:(架构)