前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >空谈系统架构设计之高并发、高可用

空谈系统架构设计之高并发、高可用

作者头像
Bruce Li
发布2020-11-10 10:29:04
5870
发布2020-11-10 10:29:04
举报

对于一个应用系统,特别是互联网系统,高并发、高可用是两个非常重要的非功能性需求,这篇文章尝试从应用系统架构角度分析如何满足这两个特性。

1

高并发,high concurrency,简单讲就是说系统可以同时支撑大量的并发请求,反映的是系统的计算能力。个人理解,高并发都可以基于scalability来实现,而scalability通常可分为两个维度:垂直扩展(scale up)和水平扩展(scale out)。垂直扩展(scale up)就是通过不断增加单机计算资源(cpu、memory等)来提高并发处理能力,而水平扩展(scale out)则是通过增加机器数量来提高并发处理能力;相对来说,scale up可能更加容易,因为对于单机系统,不用考虑分布式事务等很tricky的问题,但是由于计算机硬件发展的瓶颈,并且基于成本的考虑,通常我们优先考虑的方向是scale out,因为scale out不但可以实现高并发,同时也可以一定程度上实现高可用。

高可用,high availability,简单讲就是说系统可以在“任何时候”都保持服务在线,即使是在有服务器宕机的情况下,反映的是系统的稳定性。从理论上来说,高可用则是通过增加冗余(replication)来实现,当有节点发的故障时,自动切换到备份节点上。

2

一个典型的应用系统架构可能都包含这三层结构:web server层(比如nginx),app server层(比如tomcat)和数据库层(比如postgres),要实现高并发和高可用,一般来说都是针对这三层分别考虑实现。

2.1

web server层,通常架构在app server层前面,主要功能是负载均衡、反向代理等,显然这提高了app server层的并发处理能力,但是随之而来的就是web sever本身可能成为性能瓶颈和单点故障点。web server层可选的方案,除了常见的nginx,还有一些其它流行的方案,比如haproxy、lvs等,甚至基于硬件优化的F5。

web server的单点故障问题,反过来讲也就是高可用问题,主流的解决方案是部署多台web server,使用keepalived把多台web server组成一个集群,对外暴露一个虚拟IP(VIP),集群在任意时候只有主web server提供服务,其它从web server作为备份,如果主web server宕机,VIP则自动漂移到一台从web server。

这个方案虽然实现了高可用,但却还是存在单点性能瓶颈的问题,因为即使是号称再好的web server组件,也终究会有高并发的极限,其实本质上这就是一个如何实现web server层高并发的问题。要解决这个问题,只能做水平扩展(scale out),部署多个web server集群,每个暴露一个VIP,通过DNS轮询(或者gslp、gtm等技术)把用户请求分散到不同的web server集群上,以此实现高并发。

2.2

app server层,常规的做法就是直接scale out,部署多个duplicated的app server,借助web server层的负载均衡,一定程度既实现了高可用,也实现了高并发。

在app server层做scale out之前,需要考虑另外一个问题:由于application常常需要保存一些状态信息(比如用户的session等),如果直接scale out,用户的session可能会丢失或者不能保持。针对这个问题,现在流行的解决方案是把这些状态信息持久化到缓存中(比如redis等),这样application就是一个无状态的服务,对于无状态的服务,scale out就不会有问题。

从高并发实现的角度,可以分别从scale up和scale out两个方向考虑;回到application功能实现层面,也可以有scale up和scale out两个方向,其实它们分别对应的就是monolith模式和micro service模式,个人认为,正如scale out所展现的扩展性优点,micro service的最大好处则是一种团队合作开发模式的提高,更加敏捷高效,易于扩展。

2.3

数据库层,由于所有用户的数据都是存储在数据库,一旦数据库挂了,即使上面层的高可用、高并发做得再好,整个系统也不可用,所以数据库层的高可用、高并发尤其重要。由于数据库层是有状态的,如果和app server层类似,通过简单的scale out实现高可用、高并发,并且各个数据库节点都可以读写的话,则可能会产生数据不一致的问题(CAP理论);并且,即使可以规避这个问题,比如采用读写分离(只允许主节点写,从节点读),最终也会由于单个数据库表太大,而导致读数据性能降低,这种情况也许可以通过分表解决,但是由于只能是主节点接收写请求,主节点则很容易成为高并发写的性能瓶颈。

所以,对于有状态的数据库层,要实现高并发、高可用,应该怎样设计呢?简单讲,高可用还是通过增加冗余(replication)实现,主从节点无缝切换可以使用上面提到的keepalived方法。而高并发则是通过分库实现,把数据通过一定的算法分散到不同的数据库节点存放,这样每个数据库节点只需要处理部分流量,相比简单的scale out,这种方式一定程度减少了数据冗余,并且支持高并发写,所以我们也许可以称这种scale out方式为“复杂的scale out”。

从整体上来讲,数据库层实现高并发、高可用的方式和 kafka、redis等中间件实现的原理类似,即分别通过partition和replication来实现。

3

提高系统的高并发、高可用,除了上面提到的infrastructure层面的一些设计之外,有时候我们还需要从application本身架构层面考虑,比如:对于一个秒杀系统,也需要支持高并发、高可用,但是由于这类系统可能只是用于促销,意即可能只会在活动开始一段时间有高并发请求,并不会持续,所以可能不需要从基础架构层面提升,因为那样也意味着更高的成本。那么,针对这类场景,如何从application本身架构层面实现高并发、高可用呢?

其实,网上有很多文章介绍得很详细,但总结下来,有两个方面:

一、限流,防止突然出现大流量把系统搞挂。具体实现可以有:1)rate limit,限制用户发达请求的频率;2)把商品库存信息维护在redis中,库存扣减完了就直接返回后续所有请求。

二、削峰,秒杀请求先不做校验,直接存数据库,然后马上返回给用户“正在排队中”等信息,接着通过queue通知订单处理服务异步处理请求,完成下单操作。这样做的一个好处是,由于真正完成下单处理的时间较长,而秒杀请求直接存数据库可以很快,利用queue做一个缓冲,提高了用户可见的高并发。并且,基于这样的实现,使得系统更加resilient,在面对突发的高并发时,可以保证高可用。

4

对于高并发,除了架构层面的考虑,从服务器物理连接层面,也需要能支持更多的并发连接;随着技术的发展,现在主流的tomcat、nginx、redis等都是基于多路复用技术epoll实现,大大提高了并发连接数,进而从这的个层面有效的实现了高并发。

5

对于高可用,为了兼顾一致性(consistency)和可用性(availability),分布式数据系统常常会借助于一些分布式共识算法(consensus algorithm)来实现replication,比如zookeeper、etcd等;或者再考虑到性能,会采用一些基于分布式共识算法延伸而来的折中方案,比如kafka的ISR。数据库的高可用,除了上面提到的keepalived方法,也可以使用zookeeper来管理主从节点,并且实现主从节点自动切换(选举),类似于kafka。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 天马行空布鲁斯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档