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

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

来做个简单的比喻吧。

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

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

  • Scale-out(横向扩展):分而治之是一种常见的高并发系统设计方法,采用分布式部署的方式把流量分流开,让每个服务器都承担一部分并发和流量。

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

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

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

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

Scale-up vs Scale-out

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

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

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

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

但是有专家预测,摩尔定律可能在未来几年之内不再生效,原因是目前的芯片技术已经做到了5nm级别,在工艺上可以突破的空间不大,可能达不到摩尔定律提到的每18个月翻一番的速度了。此时,双核和多核技术的产生拯救了摩尔定律,这些技术的思路是将多个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的技术架构。

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

小结

介绍了高并发系统设计的三种通用方法:Scale-out、缓存和异步。这三种方法可以在做方案设计时灵活地运用,但它不是具体实施的方案,而是三种思想,在实际运用中会千变万化。

就拿Scale-out来说,数据库一主多从、分库分表、存储分片都是它的实际应用方案。而我们需要注意的是,在应对高并发大流量的时候,系统是可以通过增加机器来承担流量冲击的,至于要采用什么样的方案还是要具体问题具体分析。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用友NC word.docx接口存在任意文件读取漏洞 附POC

@[toc] 用友NC word.docx接口存在任意文件读取漏洞 附POC 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使…

多线程详解(未完结)

文章目录 ⭐️写在前面的话⭐️一、线程简介1.1 进程1.2 线程1.3 多线程和多进程的区别1.4 总结 二、继承实现2.1 继承Thread类例子:网图下载 2.2 实现Runnable接口 (推荐)案例:火车站买票问题案例:龟兔赛跑 2.3 实现Callable接口 (了解即可)…

虚拟机可ping树莓派树莓派无法ping虚拟机 的解决办法

问题描述 在学习交叉编译的过程中,发现了树莓派无法ping通虚拟机的问题。所以我尝试了各种ping,发现: 虚拟机可以ping通树莓派和主机树莓派可以ping通主机主机可以ping通树莓派和虚拟机唯独树莓派没法ping通虚拟机 尝试各种方法后找到一种…

突破技术障碍:软件工程师如何应对项目中的难题?

在软件开发项目中,工程师常常会遇到各种技术难题。这些难题可能涉及到复杂的算法、不兼容的系统、难以预见的软件行为,或者其他许多方面。 以下是一些策略和方法,可以帮助软件工程师有效地应对这些挑战: 1、理解问题:…

王道p150 14.假设二叉树采用二叉链表存储结构,设计一个算法,求非空二叉树 b的宽度(即具有结点数最多的那一层的结点个数) (c语言代码实现)

采用层次遍历的方法求出所有结点的层次,并将所有结点和对应的层次放在一个队列中。然后通过扫描队列求出各层的结点总数,最大的层结点总数即为二叉树的宽度。 /* A B C D E F …

下一代图片压缩格式 AVIF

长期以来我们都在为了在网络上使用什么样的图片格式而进行纠结。我们所熟知的或者运用到 Web 应用中的图片格式无非就是 PNG、JPG、GIF、SVG 或者 WebP。 HEIC是一种图像格式,上线时间还比较短,只有4年左右。 自iOS 11和 macOS High Sierra&#xff08…

GPS 定位信息获取(北斗星通 GPS)

GPS 定位信息获取(1) 首先回顾北斗星通 GPS 数据获取(1)~(5) gps_pub.cpp 将接收到的串口数据转化为GPS的经纬度信息gps_path.cpp 将经纬度信息转化为全局坐标系下的XY值,以第一个GPS经纬度为…

快递批量查询高手软件,让你轻松掌握多家快递物流信息,提升工作效率

随着电子商务的繁荣和智能化物流的普及,快递行业在全球范围内迅速发展。在这个快节奏的时代,为了提高工作效率并更好地管理物流信息,一款强大的工具——快递批量查询高手软件应运而生。这款软件可以让你轻松掌握多家快递公司的物流信息&#…

C++ 实现位图

引出 面试题:给出 40 亿个不重复的无符号整数,没有排过序。给定一个无符号整数,如何快速判断这个数是否在这 40 亿个无符号整数中。[ 腾讯面试题 ] 想法一:将 40 亿个数据存放到 set 里面,然后再查找指定的无符号整数。…

PyCharm 安装插件Vue

一、打开PyCharm工具 File -> Settings -> Plugins 二、在项目中添加Vue.js的依赖项。 npm install vue 三、页面应用

Innux(特殊位与权限)

特殊位与权限 目录: 1. SUID 2. SGID 3. SBIT 4. 文件系统属性chattr权限 5. 管理员权限sudo 1. SUID 1.1 什么是SUID SUID只对二进制可执行文件才有效(文件必须具备x权限) 执行者对该程序有 x 权限 当前程序拥有SUID时&#xff0…

MySQL性能优化,SQL调优,SQL调优的手段

文章目录 对MySQL性能的优化的理解硬件和操作系统层面的优化架构设计层面的优化MySQL程序配置优化SQL优化 SQL调优有哪几种方式1.EXPLAIN2.SQL语句中IN包含的值不应过多3.SELECT语句务必指明字段名称4.当只需要一条数据的时候,使用limit 15.如果排序字段没有用到索引…

android系统新特性——用户界面以及系统界面改进

用户界面改进 Android用户界面改进最明显的就是MD了。MD是Google于2014年推出的设计语言,它是一套完整的设计系统,包含了动画、样式、布局、组件等一系列与设计有关的元素。通过对这些行为的描述,让开发者设计出更符合目标的软件&#xff0c…

Percepio Tracealyzer 4.8.1 视觉跟踪诊断解决方案

Percepio Tracealyzer 4.8.1 视觉跟踪诊断解决方案, 是使嵌入式软件开发人员能够深入了解其运行时系统。这样可以更轻松地调试系统级问题、查找软件设计缺陷以及测量软件时序和资源使用情况。确保您的代码可靠、高效且响应迅速。 视觉运行时洞察 在运行时将 X 射线视…

计算器的模拟实现

计算器的模拟实现 一、实验题目:计算器二:实验目的:三:实验内容与实现1:【实验内容】2:【实验实现】1.计算器界面的实现,如下图所示:2:各项功能的实现,如下图…

Linux常用命令——bg命令

在线Linux命令查询工具 bg 用于将作业放到后台运行 补充说明 bg命令用于将作业放到后台运行,使前台可以执行其他任务。该命令的运行效果与在指令后面添加符号&的效果是相同的,都是将其放到系统后台执行。 在Linux系统中执行某些操作时候&…

基于YOLOv5的视频计数 — 汽车计数实现

在视频中计数对象可能看起来有挑战性,但借助Python和OpenCV的强大功能,变得令人意外地易于实现。在本文中,我们将探讨如何使用YOLO(You Only Look Once)目标检测模型在视频流或文件中计数对象。我们将该过程分解为简单…

HCIA题目解析(1)

1、【多选题】关于动态 MAC 地址表说法正确的是? A、通过报文中的源MAC地址学习获得的动态MAC表项会老化 B、通过查看指定动态MAC地址表项的个数,可以获取接口下通信的用户数 C、在设备重启后,之前的动态表项会丢失 D、在设备重启后&…

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体)

车载通信架构 —— 传统车内通信网络MOST总线(光纤传输、专精多媒体) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都…

C#,《小白学程序》第十九课:随机数(Random)第六,随机生成任意长度的大数(BigInteger)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// 除法运算为 Truffer…