高并发系统:它的通用设计方法是什么?

Java全能学习+面试指南:https://javaxiaobear.cn

我们知道,高并发代表着大流量,高并发系统设计的魅力就在于我们能够凭借自己的聪明才智设计巧妙的方案,从而抵抗巨大流量的冲击,带给用户更好的使用体验。这些方案好似能操纵流量,让流量更加平稳得被系统中的服务和组件处理。

来做个简单的比喻吧。

从古至今,长江和黄河流域水患不断,远古时期:

  • 大禹曾拓宽河道,清除淤沙让流水更加顺畅
  • 都江堰作为史上最成功的的治水案例之一,用引流将岷江之水分流到多个支流中,以分担水流压力
  • 三门峡和葛洲坝通过建造水库将水引入水库先存储起来,然后再想办法把水库中的水缓缓地排出去,以此提高下游的抗洪能力。

而我们在应对高并发大流量时也会采用类似 抵御洪水 的方案,归纳起来共有三种方法:

  • Scale-out(横向扩展)

    分而治之是一种常见的高并发系统设计方法,采用分布式部署的方式把流量分流开,让每个服务器都承担一部分并发和流量。

  • 缓存

    使用缓存来提高系统的性能,就好比用 「拓宽河道」的方式抵抗高并发大流量的冲击。

  • 异步

    在某些场景下,未处理完成之前,我们可以让请求先返回,在数据准备好之后再通知请求方,这样可以在单位时间内处理更多的请求

简单介绍了这三种方法之后,我再详细地带你了解一下,这样当你在设计高并发系统时就可以有考虑的方向了。当然了,这三种方法会细化出更多的内容,我会在后面的课程中深入讲解。

首先,我们先来了解第一种方法:Scale-out。

Scale-up vs Scale-out

著名的「摩尔定律」是由 Intel 的创始人之一戈登·摩尔于 1965 年提出的。这个定律提到,集成电路上可容纳的晶体管的数量约每隔两年会增加一倍

后来,Intel 首席执行官大卫·豪斯提出「18 个月」的说法,即预计 18 个月会将芯片的性能提升一倍,这个说法广为流传。

摩尔定律虽然描述的是芯片的发展速度,但我们可以延伸为整体的硬件性能,从 20 世纪后半叶开始,计算机硬件的性能是指数级演进的。

直到现在,摩尔定律依然生效,在半个世纪以来的 CPU 发展过程中,芯片厂商靠着在有限面积上做更小的晶体管的黑科技,大幅度地提升着芯片的性能。从第一代集成电路上只有十几个晶体管,到现在一个芯片上动辄几十亿晶体管的数量,摩尔定律指引着芯片厂商完成了技术上的飞跃。

但是有专家预测,摩尔定律可能在未来几年之内不再生效,原因是目前的芯片技术已经做到了 10nm 级别,在工艺上已经接近极限,再往上做,即使有新的技术突破,在成本上也难以被市场接受。后来,双核和多核技术的产生拯救了摩尔定律,这些技术的思路是将多个 CPU 核心压在一个芯片上,从而大大提升 CPU 的并行处理能力

我们在高并发系统设计上也沿用了同样的思路:

  • 将类似追逐摩尔定律不断提升 CPU 性能的方案叫做 Scale-up(纵向扩展)

    容纳更多的晶体管

  • 把类似 CPU 多核心的方案叫做 Scale-out

    单核心变多核心

这两种思路在实现方式上是完全不同的。

  • Scale-up

    通过购买性能更好的硬件来提升系统的并发处理能力,比方说目前系统 4 核 4G 每秒可以处理 200 次请求,那么如果要处理 400 次请求呢?很简单,我们把机器的硬件提升到 8 核 8G(硬件资源的提升可能不是线性的,这里仅为参考)。

  • Scale-out

    则是另外一个思路,它通过将多个低性能的机器组成一个分布式集群来共同抵御高并发流量的冲击。沿用刚刚的例子,我们可以使用两台 4 核 4G 的机器来处理那 400 次请求。

**那么什么时候选择 Scale-up,什么时候选择 Scale-out 呢?**一般来讲,在我们系统设计初期会考虑使用 Scale-up 的方式,因为这种方案足够简单,所谓能用堆砌硬件解决的问题就用硬件来解决,但是当系统并发超过了单机的极限时,我们就要使用 Scale-out 的方式。

Scale-out 虽然能够突破单机的限制,但也会引入一些复杂问题。比如,如果某个节点出现故障如何保证整体可用性?当多个节点有状态需要同步时,如何保证状态信息在不同节点的一致性?如何做到使用方无感知的增加和删除节点?等等。其中每一个问题都涉及很多的知识点,我会在后面的课程中深入地讲解,这里暂时不展开了。

说完了 Scale-out,我们再来看看高并发系统设计的另一种方法:缓存。

使用缓存提升性能

Web 2.0 是缓存的时代,这一点毋庸置疑。缓存遍布在系统设计的每个角落,从操作系统到浏览器,从数据库到消息队列,任何略微复杂的服务和组件中,你都可以看到缓存的影子。我们使用缓存的主要作用是提升系统的访问性能,那么在高并发的场景下,就可以支撑更多用户的同时访问。

那么为什么缓存可以大幅度提升系统的性能呢?我们知道数据是放在持久化存储中的,一般的持久化存储都是使用磁盘作为存储介质的,而普通磁盘数据由机械手臂、磁头、转轴、盘片组成,盘片又分为磁道、柱面和扇区,盘片构造图我放在下面了。

在这里插入图片描述

盘片是存储介质,每个盘片被划分为多个同心圆,信息都被存储在同心圆之中,这些 同心圆就是磁道。在磁盘工作时盘片是在高速旋转的,机械手臂驱动磁头沿着径向移动,在磁道上读取所需要的数据。我们把 磁头寻找信息花费的时间叫做寻道时间

普通磁盘的寻道时间是 10ms 左右,而相比于磁盘寻道花费的时间,CPU 执行指令和内存寻址的时间都在是 ns(纳秒)级别,从千兆网卡上读取数据的时间是在 μs(微秒)级别。所以在整个计算机体系中,磁盘是最慢的一环,甚至比其它的组件要慢几个数量级。因此,我们通常使用以内存作为存储介质的缓存,以此提升性能。

当然,缓存的语义已经丰富了很多,我们 可以将任何降低响应时间的中间存储都称为缓存。缓存的思想遍布很多设计领域,比如在操作系统中 CPU 有多级缓存,文件有 Page Cache 缓存,你应该有所了解。

异步处理

异步 也是一种常见的高并发设计方法,我们在很多文章和演讲中都能听到这个名词,与之共同出现的还有它的反义词:同步。比如,分布式服务框架 Dubbo 中有同步方法调用和异步方法调用,IO 模型中有同步 IO 和异步 IO。

那么什么是同步,什么是异步呢? 以方法调用为例,同步调用代表调用方要阻塞等待被调用方法中的逻辑执行完成。这种方式下,当被调用方法响应时间较长时,会造成调用方长久的阻塞,在高并发下会造成整体系统性能下降甚至发生雪崩。

异步调用恰恰相反,调用方不需要等待方法逻辑执行完成就可以返回执行其他的逻辑,在被调用方法执行完毕后再通过回调、事件通知等方式将结果反馈给调用方。

异步调用在大规模高并发系统中被大量使用,比如我们熟知的 12306 网站。 当我们订票时,页面会显示系统正在排队,这个提示就代表着系统在异步处理我们的订票请求。在 12306 系统中查询余票、下单和更改余票状态都是比较耗时的操作,可能涉及多个内部系统的互相调用,如果是同步调用就会像 12306 刚刚上线时那样,高峰期永远不可能下单成功。

而采用异步的方式,后端处理时会把请求丢到消息队列中,同时快速响应用户,告诉用户我们正在排队处理,然后释放出资源来处理更多的请求。订票请求处理完之后,再通知用户订票成功或者失败。

处理逻辑后移到异步处理程序中,Web 服务的压力小了,资源占用的少了,自然就能接收更多的用户订票请求,系统承受高并发的能力也就提升了。

在这里插入图片描述

既然我们了解了这三种方法,那么是不是意味着在高并发系统设计中,开发一个系统时要把这些方法都用上呢?当然不是,系统的设计是不断演进的

罗马不是一天建成的,系统的设计也是如此。 不同量级的系统有不同的痛点,也就有不同的架构设计的侧重点。如果都按照百万、千万并发来设计系统,电商一律向淘宝看齐,IM 全都学习微信和 QQ,那么这些系统的命运一定是灭亡。

因为淘宝、微信的系统虽然能够解决同时百万、千万人同时在线的需求,但其内部的复杂程度也远非我们能够想象的。盲目地追从只能让我们的架构复杂不堪,最终难以维护。就拿从单体架构往服务化演进来说,淘宝也是在经历了多年的发展后,发现系统整体的扩展能力出现问题时,开始启动服务化改造项目的。

我之前也踩过一些坑, 参与的一个创业项目在初始阶段就采用了服务化的架构,但由于当时人力有限,团队技术积累不足,因此在实际项目开发过程中,发现无法驾驭如此复杂的架构,也出现了问题难以定位、系统整体性能下降等多方面的问题,甚至连系统宕机了都很难追查到根本原因,最后不得不把服务做整合,回归到简单的单体架构中。

所以我建议一般系统的演进过程应该遵循下面的思路:

  • 最简单的系统设计满足业务需求和流量现状,选择最熟悉的技术体系。
  • 随着流量的增加和业务的变化,修正架构中存在问题的点,如单点问题,横向扩展问题,性能无法满足需求的组件。在这个过程中,选择社区成熟的、团队熟悉的组件帮助我们解决问题,在社区没有合适解决方案的前提下才会自己造轮子。
  • 当对架构的小修小补无法满足需求时,考虑重构、重写等大的调整方式以解决现有的问题。

以淘宝为例, 当时在业务从 0 到 1 的阶段是通过购买的方式快速搭建了系统。而后,随着流量的增长,淘宝做了一系列的技术改造来提升高并发处理能力,比如数据库存储引擎从 MyISAM 迁移到 InnoDB,数据库做分库分表,增加缓存,启动中间件研发等。

当这些都无法满足时就考虑对整体架构做大规模重构,比如说著名的「五彩石」项目让淘宝的架构从单体演进为服务化架构。正是通过逐步的技术演进,淘宝才进化出如今承担过亿 QPS 的技术架构。

归根结底一句话:高并发系统的演进应该是循序渐进,以解决系统中存在的问题为目的和驱动力的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/172787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis-Plus 租户使用

Mybatis-Plus 租户使用 文章目录 Mybatis-Plus 租户使用一. 前言1.1 租户存在的意义1.2 租户框架 二. Mybatis-plus 租户2.1 租户处理器2.2 前置准备1. 依赖2. 表及数据准备3. 代码生成器 2.3 使用 三. 深入使用3.1 前言3.2 租户主体设值,取值3.3 部分表全量db操作3…

【古诗生成AI实战】之三——任务加载器与预处理器

本章内容属于数据处理阶段,将分别介绍任务加载器task和预处理器processor。 [1] 数据集 在深入探讨数据处理的具体步骤之前,让我们先了解一下我们将要使用的数据集的形式。 本项目采用的是七绝数据集,总计83072条古诗,其形式如下&…

大语言模型损失函数详解

我们可以把语言模型分为两类: 自动回归式语言模型:自动回归式语言模型在本质上是单向的,也就是说,它只沿着一个方向阅读句子。正向(从左到右)预测;反向(从右到左)预测。…

linux复习笔记04(小滴课堂)

软件安装rpm方式介绍: 先去挂载光盘: 要确保这是已连接状态。 我们查看到已经挂载成功了。 进到这个目录下。 我们可以看到这有很多rpm软件包。 man rpm: 可以看到很多参数,但是我们不需要全部掌握。 举例: 这就是告诉我们需要安…

2017年五一杯数学建模C题宜居城市问题值解题全过程文档及程序

2017年五一杯数学建模 C题 宜居城市问题 原题再现 城市宜居性是当前城市科学研究领域的热点议题之一,也是政府和城市居民密切关注的焦点。建设宜居城市已成为现阶段我国城市发展的重要目标,对提升城市居民生活质量、完善城市功能和提高城市运行效率具有重要意义。…

深信服超融合一体机提示:内存ECC

PS:此事件分享主要来源于季度巡检时发现的超融合一体机红灯闪烁异常,接入IPMI端口查看日志发现持续提示内存ECC; 因为是只有3.05这一天发现了有这个告警的提示,所以当时清除了日志以后重启了BMC服务就解决了;但是如果清…

【虚拟机】在VM中安装 CentOS 7

1.2.创建虚拟机 Centos7是比较常用的一个Linux发行版本,在国内的使用比例还是比较高的。 大家首先要下载一个Centos7的iso文件,我在资料中给大家准备了一个mini的版本,体积不到1G,推荐大家使用: 我们在VMware《主页》…

ctfshow刷题web入门--1--ljcsd

文章目录 ctf.show。信息搜集web1web2web3web4web5web6web7web8web9web10web11web12web13web14web15web16web17web18web19web20。爆破。知识1.1 播种随机数生成器-mt_srand。参考web21--重点web22--做不出来web23web24web25web26web27web28。。。命令执行。知识1 绕过正则表达式…

Windows安装Python环境(V3.6)

文章目录 一:进入网址:https://www.python.org/downloads/ 二:执行安装包 默认C盘,选择自定义安装目录 记得勾选add python path 下面文件夹最好不要有 . 等特殊符号 可以创建 python36 如果安装失败Option可以选默认的&#x…

PCIE链路训练-状态机描述4

Recovery Recovery.RcvrLock (1)如果link是在8.0GT/s或以上的速率工作,那么rx只会认为当前lane获得Block alignment之后收到的TS0,TS1,TS2是有效的。如果进入当前状态是从L1或recovery.speed或L0s,获取Blo…

【第三节:微信小程序 3、app.js配置】微信小程序入门,以思维导图的方式展开3

目录 提供了2个函数: app.js配置 【第三节:微信小程序 3、app.js配置】微信小程序入门,以思维导图的方式展开3 提供了2个函数: app() getApp() --------------------------- app.js配置 App() 功能 Ap…

基于springboot实现高校食堂移动预约点餐系统【项目源码】计算机毕业设计

基于springboot实现高校食堂移动预约点餐系统演示 Java语言简介 Java是由SUN公司推出,该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称,也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备…

如何减少40%的Docker构建时间

随着Docker的普及,许多公司的产品会将组件构建为Docker镜像。但随着时间的推移,一些镜像变得越来越大,对应的CI构建也变得越来越慢。 如果能在喝完一杯咖啡的时间(不超过5分钟)内完成构建,将是一个理想状态…

Proteus仿真--基于字符液晶显示的频率计

本文介绍基于数码管的频率计(完整仿真源文件及代码见文末链接) 仿真图如下 本设计中80C51单片机作为主控,用字符液晶作为显示模块,按下按键K1后可进行频率测量并显示 仿真运行视频 Proteus仿真--基于字符液晶显示的频率计 附完…

设计模式—接口隔离原则(ISP)

1.背景 2002 年罗伯特C.马丁给“接口隔离原则”的定义是:客户端不应该被迫依赖于它不使用的方法(Clients should not be forced to depend on methods they do not use)。该原则还有另外一个定义:一个类对另一个类的依赖应该建立…

sql语句在字段中使用select

有两个表如下;产品表,产品评论表; 查询全部产品信息和每种产品的评论数量; 这也是子查询的一种; select * from product1; select * from comment; SELECT product1.*,(select count(id) from comment where product1…

PCIE链路训练-状态机描述3

Configuration.Idle 1.当使用8b/10b编码时,non-flit模式下,在所用配置的lane上发送s Idle data Symbols,在flit mode下发送IDLE flit。 2.linkup 0 link两端的component均支持64.0GT/s的速率,根据进入此状态之前发送的8个TS2或…

【Linux】进程间通信

进程间通信 1. 进程间通信介绍1.1 进程间通信目的1.2 进程间通信发展1.3 进程间通信分类1.4 进程间通信的本质理解 2. 管道3. 匿名管道3.1 pipe()函数3.2 站在文件描述符角度-深度理解管道3.3 站在内核角度-管道本质3.4 匿名管道使用步骤3.4 管道读写规则3.5 管道的读与写的五种…

一文带你了解机器翻译的前世今生

引言 我们都知道谷歌翻译,这个网站可以像变魔术一样在100 种不同的人类语言之间进行翻译。它甚至可以在我们的手机和智能手表上使用: 谷歌翻译背后的技术被称为机器翻译。它的出现改变了世界交流方式。 事实证明,在过去几年中,深…

springboot核心原理之@SpringbootApplication

1.SpringbootApplication Configuration标志的类 在spring ioc启动的时候就会加载创建这个类对象 EnableAutoConfiguration 中有两个注解 (1)AutoConfigurationPackage 扫描主程序包(主程序main所在包及其子包) 可以看到这个类 : static c…