高并发架构设计

我的架构设计专栏:https://www.nowcoder.com/creation/manager/columnDetail/0ybvLm

我的java八股专栏:https://www.nowcoder.com/creation/manager/columnDetail/j8ZZk0

欢迎订阅和点赞!

前言

高并发解决的核心问题是在同一时间上有大量的请求过来,然后我们的系统要怎么抗住这些请求带来的压力。比如在线直播服务,同时有上百万甚至上千万人观看。比如秒杀品,同时有大量用户涌入。

高并发是从业务角度去描述系统的能力,实现高并发的手段可以采用分布式,也可以采用缓存等,当然也包括多线程、协程,但远远不仅如此;高并发的基本表现为单位时间内系统能够同时处理的请求数,高并发的核心是对资源的有效压榨,有限的资源应对大量的请求。

现代互联网服务,基本上都要考虑高并发问题,因为一般的产品,用户的请求量都很大。

分析角度

高并发架构设计,需要从三大层来建设和分析

● 基础设施层:这个是最基础的依赖,主要是一些服务的部署。针对大公司而言,一般都有成熟的系统和基础设施来承载,可能针对业务开发的同学来看,平时关注的的细节并不深入,但是不妨碍我们从全局角度来剖析高并发的设计。

● 服务端架构层:这个是我们重点要关注的架构设计,架构设计不合理,就很难抗住高并发,主要包括各种架构和模块的设计。

● 服务应用层: 这个主要是针对我们写的代码来进行优化改进。从代码架构、代码性能等方便去抗并发。

1. 基础设施层

部署:多 IDC + 异地多活

多活可以分为同城多活、异地多活等等,实现方式也有多种,比如阿里使用的单元化方案,饿了么使用的是多中心的方案,关于饿了么多活的实现可以参考饿了么多活实现分享。当时做多活的主要出发点是保证系统的高可用性,避免单IDC的单点故障问题,同时由于每个机房的流量都变成了总流量的1/N,也变相提升了系统容量,在高并发的场景下可以抗更多的流量。下图是饿了么多活的整体架构,来源于上面饿了么多活实现的分享文章中。

基础设施层一般包含了服务器、IDC、部署方式等等。目前而言,我们一般都用容器部署的方式,而容器的底层能力基本也都是建立在 k8s 容器层之上的,服务本身的部署管理已经有成熟的设施帮我们实现了。具体到部署方式,包括但不限于:

● 多 IDC 部署。比如服务同时在广州、上海两地部署。 这个依赖我们的服务是无状态的

● 其他的参考下 异地多活架构等相关部署。

监控:可观测性

系统的可观测性主要包含三个部分: logging、tracing、metrics。 这个一般都要引入可观测系统,这样才能帮助我们在异常的时候能够快速定位问题。属于必备设施,一般而言,公司应该都有专门的团队去做这个事情。

2. 服务架构层

服务端架构层是我们重点要关注的,这个也是考量个人架构能力的最关键部分。

系统分层设计:分层、分割、分布式

● • 架构分层

○ • 应用层:网站首页,用户中心,商品中心,购物车,红包业务,活动中心等,负责具体业务和视图展示

○ • 服务层:订单服务,用户管理服务,红包服务,商品服务等,为应用层提供服务支持

○ • 数据层:关系数据库,nosql数据库 等,提供数据存储查询服务

○ • 将系统在横向维度上切分成几个部分,每一层的功能职责要足够单一,然后通过上层对下层的依赖和调度组成一个完整的系统

○ • 比如把电商系统分成:应用层,服务层,数据层。(具体分多少个层次根据自己的业务场景)

● • 业务分割

○ • 在纵向方面对业务进行切分,将一块相对复杂的业务分割成不同的模块单元,对应的是模块的划分,通过合理的模块划分,使得每个模块都能可以满足 高内聚低耦合 的设计要求,这样不同的模块可以分布式部署,也能提高并发处理能力和功能扩展

○ • 比如用户中心可以分割成:账户信息模块,订单列表模块,充值模块,优惠券模块等

● • 分布式

○ • 分布式应用和服务,将分层或者分割后的业务分布式部署,独立的应用服务器,数据库,缓存服务器,当业务达到一定用户量的时候,再进行服务器均衡负载,数据库,缓存主从集群

集群架构设计:应用集群、数据集群

应对高并发系统,不管是应用层面还是数据层面,单机都不可能搞定,因此都需要搭建集群架构,然后通过负载均衡来对外提供服务。同时集群架构还能保证系统的可用性,当某台服务或者机器异常,负载均衡会自动剔除,不会影响对外服务。

● • 应用服务器集群

○ • nginx 反向代理

○ • slb

○ • LVS …

● • 数据集群(关系/nosql数据库)

○ • 主从分离,一主多从

○ • 数据读写分离

数据库设计:读写分离+分库分表+冷热分离

应对高并发,数据的存储,首先就要做好预估,先进行分库分表 和 读写分离,最后可以根据情况来看是否冷热分离:

读写分离模式和分库分表模式推荐优先使用读写分离模式,只有在不满业务需求的情况才才考虑使用分库分表模式。原因是分库分表模式虽然能显著提升数据库的容量,但会增加系统复杂性,而且由于只能支持少数的几个维度读写,从某种意义上来说对业务系统也是一种限制,因此在设计分库分表方案的时候需要结合具体业务场景,更全面的考虑。

● 读写分离。

○ 互联网系统大多数都是读多写少,因此读写分离可以帮助主库抗量。一般我们都是一主多从的架构,可以抗量,也可以保证数据不丢。读写分离只能解决 QPS 高,但是无法解决 TPS 高,比如写入的量足够大的话(TPS 高),就得分库分表。比如现在有1万QPS的以及1K的TPS,假设在1主5从的配置下,主库只承担1K的TPS,每个从库承担2K的QPS,这种量级对DB来说是完全可接受的,相比读写分离改造前,DB的压力明显小了许多。

○ 无法解决TPS高的问题:从库虽然能解决QPS高的问题,但没办法解决TPS高的问题,所有的写请求只有主库能处理,一旦TPS过高,DB依然有宕机的风险。

○ 主从延迟问题:MySQL默认的主从复制是异步的,如果在主库插入数据后马上去从库查询,可能会发生查不到的情况。正常情况下主从复制会存在毫秒级的延迟,在DB负载较高的情况下可能存在秒级延迟甚至更久,但即使是毫秒级的延迟,对于实时性要求较高的业务来说也是不可忽视的。所以在一些关键的查询场景,我们会将查询请求绑定到主库来避免主从延迟的问题。关于主从延迟的优化网上也有不少的文章分享,这里就不再赘述。

○ 从库数量有限:一个主库能挂载的从库数量是很有限的,没办法做到无限的水平扩展。从库越多,虽然理论上能承受的QPS就越高,但是从库过多会导致主库主从复制IO压力更大,造成更高的延迟,从而影响业务,所以一般来说只会在主库后挂载有限的几个从库。

● • 分库分表。

○ 当读写分离不能满足业务需要时,就需要考虑使用分库分表模式了。当确定要对数据库做优化时,应该优先考虑使用读写分离的模式,只有在读写分离的模式已经没办法承受业务的流量时,我们才考虑分库分表的模式。

○ 分库就是把原来都在一个DB实例中的表,按一定的规则拆分到N个DB实例中,每个DB实例都会有一个master,相当于是多mater的架构,同时为了保证高可用性,每个master至少要有1个slave,来保证master宕机时slave能及时顶上,同时也能保证数据不丢失。拆分完后每个DB实例中只会有部分表。由于是多master的架构,分库分表除了包含读写分离模式的所有优点外,还可以解决读写分离架构中无法解决的TPS过高的问题,同时分库分表理论上是可以无限横向扩展的,也解决了读写分离架构下从库数量有限的问题。

○ 事务问题:在业务中我们会使用事务来处理多个数据库操作,通过事务的4个特性——一致性、原子性、持久性、隔离性来保证业务流程的正确性。在分库分表后,会将一张表拆分成N张子表,这N张子表可能又在不同的DB实例中,因此虽然逻辑上看起来还是一张表,但其实已经不在一个DB实例中了,这就造成了无法使用事务的问题。最常见的就是在批量操作中,在分库分表前我们可以同时把对多个订单的操作放在一个事务中,但在分库分表后就不能这么干了,因为不同的订单可能属于不同用户,假设我们按用户来分库分表,那么不同用户的订单表位于不同的DB实例中,多个DB实例显然没办法使用一个事务来处理,这就需要借助一些其他的手段来解决这个问题。在分库分表后应该要尽量避免这种跨DB实例的操作,如果一定要这么使用,优先考虑使用补偿等方式保证数据最终一致性,如果一定要强一致性,常用的方案是通过分布式事务的方式。

○ 数据迁移:

■ 分库分表一般是需要进行数据迁移的,通过数据迁移将原有的单表数据迁移到分库分表后的库表中。数据迁移的方案常见的有两种,第一种是停机迁移,顾名思义,这种方式简单粗暴,好处是能一步到位,迁移周期短,且能保证数据一致性,坏处是对业务有损,某些关键业务可能无法接受几分钟或更久的停机迁移带来的业务损失。

■ 另外一种方案是双写,这主要是针对新增的增量数据,存量数据可以直接进行数据同步,关于如何进行双写迁移网上已经有很多分享了,这里也就不赘述,核心思想是同时写老库和新库。双写的好处是对业务的影响小,但也更复杂,迁移周期更长,容易出现数据不一致问题,需要有完整的数据一致性保证方案支持。

● • 冷热分离。

○ 针对业务场景而言,如果数据有冷热之分的话,可以将历史冷数据与当前热数据分开存储,这样可以减轻当前热数据的存储量,可以提高性能。

缓存设

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

本专栏价格永远为19.9元! 不想当架构师的后端开发工程师不是好码农! 此专栏一方面用于存放我的架构设计学习笔记, 另外我会在本专栏加入一系列最常问八股问题帖子,内容就是我根据自己的面试经历和网上的面经,去筛选八股里面哪些是最常被问到的问题把它们整理出来,大家可以在面试前一两个小时快速把这一系列最常问八股的帖子拿出来看看,临时抱佛脚的效果应该很好

全部评论

相关推荐

05-15 01:17
门头沟学院 C++
本人双非二本,主要语言技术栈是C++,Linux,服务器开发的一些技能(熟悉Linux),工具类比较熟悉docker,redis,MySQL,也学了很多扩展的技能:protobuf序列化,Python,git,包括软件测试以及工具使用啥的(Selenium,jmeter,Postman),最初期望是找开发岗,可是约面的很少。目前在一家量化公司做系统工程师实习,带我的人挺好的,但是不到一个月他就辞职了,他跟我说这个岗就是运维,偶尔写点Python脚本开发,你有什么想干的或者想学的告诉我,尽量安排,然后教了我k8s,k8s部署zabbix实现集群监控,对接飞书机器人发送播报,nginx配置的一些杂活(负载均衡,安全防护),还有就是CICD。业余时间在学分布式架构的一些知识,redis集群,MySQL集群,系统架构,消息队列这些,他跟我说我教你的这些可以包装到简历上,找相关工作有帮助,然后给了我一些运维八股文,说这公司有钱待遇也可以,转正拿10k还是可以的(在上海),然后介绍了一些后续的学习路线,ELK,感兴趣可以学一下NAS这些,他不推荐我走C++后端开发,岗位少还卡学历,让我走运维开发,或者云计算这两个方向还行,他说运维顶不住会的多,不光学的多还要深等等这些建议。交代完这些几天就离职了。       但是我看网上说运维工资低,没有技术含量,前景不行,看的我好焦虑,从C到数据结构,再到C++,再到Linux,Linux系统内核,Linux系统编程,Linux网络编程…,从大一下开始学到现在也已经两年,感觉做运维跟我学的不怎么沾边,一切努力好像都白费了😭,各位大佬有没有什么建议。 
点赞 评论 收藏
分享
评论
5
9
分享

创作者周榜

更多
牛客网
牛客企业服务