03 _ 系统设计目标(一):如何提升系统性能?

提到互联网系统设计,可能听到最多的词就是“三高”,也就是“高并发”“高性能”“高可用”,它们是互联网系统架构设计永恒的主题。这里将整体探讨下高并发系统设计的目标,然后在此基础上,探讨下:如何提升系统的性能?

高并发系统设计的三大目标:高性能、高可用、可扩展

高并发,是指运用设计手段让系统能够处理更多的用户并发请求,也就是承担更大的流量。它是一切架构设计的背景和前提,脱离了它去谈性能和可用性是没有意义的。很显然嘛,你在每秒一次请求和每秒一万次请求,两种不同的场景下,分别做到毫秒级响应时间和五个九(99.999%)的可用性,无论是设计难度还是方案的复杂度,都不是一个级别的。

而性能和可用性,是我们实现高并发系统设计必须考虑的因素。

性能反映了系统的使用体验,想象一下,同样承担每秒一万次请求的两个系统,一个响应时间是毫秒级,一个响应时间在秒级别,它们带给用户的体验肯定是不同的。

可用性则表示系统可以正常服务用户的时间。我们再类比一下,还是两个承担每秒一万次的系统,一个可以做到全年不停机、无故障,一个隔三差五宕机维护,如果你是用户,你会选择使用哪一个系统呢?答案不言而喻。

另一个耳熟能详的名词叫“可扩展性”,它同样是高并发系统设计需要考虑的因素。为什么呢?我来举一个具体的例子。

流量分为平时流量和峰值流量两种,峰值流量可能会是平时流量的几倍甚至几十倍,在应对峰值流量的时候,我们通常需要在架构和方案上做更多的准备。这就是淘宝会花费大半年的时间准备双十一,也是在面对“明星离婚”等热点事件时,看起来无懈可击的微博系统还是会出现服务不可用的原因。而易于扩展的系统能在短时间内迅速完成扩容,更加平稳地承担峰值流量。

高性能、高可用和可扩展,是我们在做高并发系统设计时追求的三个目标

接下来正式进入今天的话题:如何提升系统的性能?

性能优化原则

“天下武功,唯快不破”。性能是系统设计成功与否的关键,实现高性能也是对程序员个人能力的挑战。不过在了解实现高性能的方法之前,我们先明确一下性能优化的原则。

首先,性能优化一定不能盲目,一定是问题导向的。脱离了问题,盲目地提早优化会增加系统的复杂度,浪费开发人员的时间,也因为某些优化可能会对业务上有些折中的考虑,所以也会损伤业务。

其次,性能优化也遵循“八二原则”,即你可以用20%的精力解决80%的性能问题。所以我们在优化过程中一定要抓住主要矛盾,优先优化主要的性能瓶颈点。

再次,性能优化也要有数据支撑。在优化过程中,你要时刻了解你的优化让响应时间减少了多少,提升了多少的吞吐量。

最后,性能优化的过程是持续的。高并发的系统通常是业务逻辑相对复杂的系统,那么在这类系统中出现的性能问题通常也会有多方面的原因。因此,我们在做性能优化的时候要明确目标,比方说,支撑每秒1万次请求的吞吐量下响应时间在10ms,那么我们就需要持续不断地寻找性能瓶颈,制定优化方案,直到达到目标为止。

在以上四个原则的指引下,掌握常见性能问题的排查方式和优化手段,就一定能让你在设计高并发系统时更加游刃有余。

性能的度量指标

性能优化的第三点原则中提到,对于性能我们需要有度量的标准,有了数据才能明确目前存在的性能问题,也能够用数据来评估性能优化的效果。所以明确性能的度量指标十分重要。

一般来说,度量性能的指标是系统接口的响应时间,但是单次的响应时间是没有意义的,你需要知道一段时间的性能情况是什么样的。所以,我们需要收集这段时间的响应时间数据,然后依据一些统计方法计算出特征值,这些特征值就能够代表这段时间的性能情况。我们常见的特征值有以下几类。

  • 平均值

顾名思义,平均值是把这段时间所有请求的响应时间数据相加,再除以总请求数。平均值可以在一定程度上反应这段时间的性能,但它敏感度比较差,如果这段时间有少量慢请求时,在平均值上并不能如实地反应。

举个例子,假设我们在30s内有10000次请求,每次请求的响应时间都是1ms,那么这段时间响应时间平均值也是1ms。这时,当其中100次请求的响应时间变成了100ms,那么整体的响应时间是(100 * 100 + 9900 * 1) / 10000 = 1.99ms。你看,虽然从平均值上来看仅仅增加了不到1ms,但是实际情况是有1%的请求(100/10000)的响应时间已经增加了100倍。所以,平均值对于度量性能来说只能作为一个参考。

  • 最大值

这个更好理解,就是这段时间内所有请求响应时间最长的值,但它的问题又在于过于敏感了。

还拿上面的例子来说,如果10000次请求中只有一次请求的响应时间达到100ms,那么这段时间请求的响应耗时的最大值就是100ms,性能损耗为原先的百分之一,这种说法明显是不准确的。

  • 分位值

分位值有很多种,比如90分位、95分位、75分位。以90分位为例,我们把这段时间请求的响应时间从小到大排序,假如一共有100个请求,那么排在第90位的响应时间就是90分位值。分位值排除了偶发极慢请求对于数据的影响,能够很好地反应这段时间的性能情况,分位值越大,对于慢请求的影响就越敏感。

在我来看,分位值是最适合作为时间段内,响应时间统计值来使用的,在实际工作中也应用最多。除此之外,平均值也可以作为一个参考值来使用。

我在上面提到,脱离了并发来谈性能是没有意义的,我们通常使用吞吐量或者响应时间来度量并发和流量,使用吞吐量的情况会更多一些。但是你要知道,这两个指标是呈倒数关系的。

这很好理解,响应时间1s时,吞吐量是每秒1次,响应时间缩短到10ms,那么吞吐量就上升到每秒100次。所以,一般我们度量性能时都会同时兼顾吞吐量和响应时间,比如我们设立性能优化的目标时通常会这样表述:在每秒1万次的请求量下,响应时间99分位值在10ms以下。

那么,响应时间究竟控制在多长时间比较合适呢?这个不能一概而论。

从用户使用体验的角度来看,200ms是第一个分界点:接口的响应时间在200ms之内,用户是感觉不到延迟的,就像是瞬时发生的一样。而1s是另外一个分界点:接口的响应时间在1s之内时,虽然用户可以感受到一些延迟,但却是可以接受的,超过1s之后用户就会有明显等待的感觉,等待时间越长,用户的使用体验就越差。所以,健康系统的99分位值的响应时间通常需要控制在200ms之内,而不超过1s的请求占比要在99.99%以上。

现在你了解了性能的度量指标,那我们再来看一看,随着并发的增长我们实现高性能的思路是怎样的。

高并发下的性能优化

假如说,你现在有一个系统,这个系统中处理核心只有一个,执行的任务的响应时间都在10ms,它的吞吐量是在每秒100次。那么我们如何来优化性能从而提高系统的并发能力呢?主要有两种思路:一种是提高系统的处理核心数,另一种是减少单次任务的响应时间。

1.提高系统的处理核心数

提高系统的处理核心数就是增加系统的并行处理能力,这个思路是优化性能最简单的途径。拿上一个例子来说,你可以把系统的处理核心数增加为两个,并且增加一个进程,让这两个进程跑在不同的核心上。这样从理论上,你系统的吞吐量可以增加一倍。当然了,在这种情况下,吞吐量和响应时间就不是倒数关系了,而是:吞吐量=并发进程数/响应时间。

计算机领域的阿姆达尔定律(Amdahl’s law)是吉恩·阿姆达尔在1967年提出的。它描述了并发进程数与响应时间之间的关系,含义是在固定负载下,并行计算的加速比,也就是并行化之后效率提升情况,可以用下面公式来表示:

(Ws + Wp) / (Ws + Wp/s)

其中,Ws表示任务中的串行计算量,Wp表示任务中的并行计算量,s表示并行进程数。从这个公式我们可以推导出另外一个公式:

1/(1-p+p/s)

其中,s还是表示并行进程数,p表示任务中并行部分的占比。当p为1时,也就是完全并行时,加速比与并行进程数相等;当p为0时,即完全串行时,加速比为1,也就是说完全无加速;当s趋近于无穷大的时候,加速比就等于1/(1-p),你可以看到它完全和p成正比。特别是,当p为1时,加速比趋近于无穷大。

以上公式的推导过程有些复杂,你只需要记住结论就好了。

我们似乎找到了解决问题的银弹,是不是无限制地增加处理核心数就能无限制地提升性能,从而提升系统处理高并发的能力呢?很遗憾,随着并发进程数的增加,并行的任务对于系统资源的争抢也会愈发严重。在某一个临界点上继续增加并发进程数,反而会造成系统性能的下降,这就是性能测试中的拐点模型。

从图中你可以发现,并发用户数处于轻压力区时,响应时间平稳,吞吐量和并发用户数线性相关。而当并发用户数处于重压力区时,系统资源利用率到达极限,吞吐量开始有下降的趋势,响应时间也会略有上升。这个时候,再对系统增加压力,系统就进入拐点区,处于超负荷状态,吞吐量下降,响应时间大幅度上升。

所以我们在评估系统性能时通常需要做压力测试,目的就是找到系统的“拐点”,从而知道系统的承载能力,也便于找到系统的瓶颈,持续优化系统性能。

说完了提升并行能力,我们再看看优化性能的另一种方式:减少单次任务响应时间。

2.减少单次任务响应时间

想要减少任务的响应时间,首先要看你的系统是CPU密集型还是IO密集型的,因为不同类型的系统性能优化方式不尽相同。

CPU密集型系统中,需要处理大量的CPU运算,那么选用更高效的算法或者减少运算次数就是这类系统重要的优化手段。比方说,如果系统的主要任务是计算Hash值,那么这时选用更高性能的Hash算法就可以大大提升系统的性能。发现这类问题的主要方式,是通过一些Profile工具来找到消耗CPU时间最多的方法或者模块,比如Linux的perf、eBPF等。

IO密集型系统指的是系统的大部分操作是在等待IO完成,这里IO指的是磁盘IO和网络IO。我们熟知的系统大部分都属于IO密集型,比如数据库系统、缓存系统、Web系统。这类系统的性能瓶颈可能出在系统内部,也可能是依赖的其他系统,而发现这类性能瓶颈的手段主要有两类。

第一类是采用工具,Linux的工具集很丰富,完全可以满足你的优化需要,比如网络协议栈、网卡、磁盘、文件系统、内存,等等。这些工具的用法很多,你可以在排查问题的过程中逐渐积累。除此之外呢,一些开发语言还有针对语言特性的分析工具,比如说Java语言就有其专属的内存分析工具。

另外一类手段就是可以通过监控来发现性能问题。在监控中我们可以对任务的每一个步骤做分时的统计,从而找到任务的哪一步消耗了更多的时间。这一部分在演进篇中会有专门的介绍,这里就不再展开了。

那么找到了系统的瓶颈点,我们要如何优化呢?优化方案会随着问题的不同而不同。比方说,如果是数据库访问慢,那么就要看是不是有锁表的情况、是不是有全表扫描、索引加的是否合适、是否有JOIN操作、需不需要加缓存,等等;如果是网络的问题,就要看网络的参数是否有优化的空间,抓包来看是否有大量的超时重传,网卡是否有大量丢包等。

总而言之,“兵来将挡水来土掩”,我们需要制定不同的性能优化方案来应对不同的性能问题。

有时候在遇到性能问题的时候会束手无策,这里总结出几点:

  • 数据优先,你做一个新的系统在上线之前一定要把性能监控系统做好;
  • 掌握一些性能优化工具和方法,这就需要在工作中不断地积累;
  • 计算机基础知识很重要,比如说网络知识、操作系统知识等等,掌握了基础知识才能让你在优化过程中抓住性能问题的关键,也能在性能优化过程中游刃有余。

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

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

相关文章

如何使用 WordPress搭建一个博客?详细搭建教程

域名服务器环境WordPress程序个人博客或企业官网等 前言:域名服务器是需要一些费用域名是一年服务器需要租赁3个月以上的才有备案码推荐购买一年,WordPress主题和插件有免费和付费的看自己需求 一、环境已经安装好了已经在运营项目咋就跳过从建站开始 二、进入根目录…

曲线拟合:走进数据建模中的艺术与科学

在现代科学和工程领域,曲线拟合是一项重要的数据分析技术,它可以通过数学模型来近似描述实际数据中的复杂关系。本文将详细介绍曲线拟合的基本概念、方法和应用领域,并探究其在数据建模中的艺术与科学。 第一节:曲线拟合的基本概…

IBM X3650M4安装ESXI6.5卡在/lsl_mr3.v00

环境:IBM X3650M4服务器双盘配置raid1,通过rufus制作启动U盘,安装VMware Vsphere 5.5系统 问题:卡在/lsi_mr3.v00界面无法往下运行(两台配置一样的机器遇到同样的问题) 解决方案: 直接在U盘根…

远程安全访问JumpServer:使用cpolar内网穿透搭建固定公网地址

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机,是符合 4A 规范的专业运维安全审计系统。JumpS…

pop链反序列化 [MRCTF2020]Ezpop1

打开题目 网站源码为 Welcome to index.php <?php //flag is in flag.php //WTF IS THIS? //Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95 //And Crack It! class Modifier {protected …

【问题思考总结】多维随机变量函数的分布的两种情况的计算方法【离连/连连】

问题 今天做李六第一套的时候发现&#xff0c;有的时候&#xff0c;面对这种第二问的题&#xff0c;很自然地就想到了Fz&#xff08;z&#xff09;&#xff0c;然后进行化简&#xff0c;但是有的时候&#xff0c;像这道题&#xff0c;就突然发现P{XY<z}是一个非常复杂的形式…

【java】-D参数使用

在开发过程中我们使用开源工具经常会用到在启动命令时候加入一个 -Dxxx 类型的参数。到底-Dxxx是干什么用的了。 官方文档 地址&#xff1a;文档地址 java命令使用 下面是来源于官方文档&#xff1a; java [options] classname [args] java [options] -jar filename [args…

VUE留言板

效果预览图 完整代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>作业</title><styl…

Element-UI Upload 手动上传文件的实现与优化

文章目录 引言第一部分&#xff1a;Element-UI Upload 基本用法1.1 安装 Element-UI1.2 使用 <el-upload> 组件 第二部分&#xff1a;手动上传文件2.1 手动触发上传2.2 手动上传时的文件处理 第三部分&#xff1a;性能优化3.1 并发上传3.2 文件上传限制 结语 &#x1f38…

【Linux】常见指令及周边知识(一)

【Linux】常见指令及周边知识&#xff08;一&#xff09; 一、初始Linux操作系统1.Linux背景2.如何使用Linux 二、学习Linux之前的预备周边知识&#xff08;重点&#xff09;&#xff1a;1.什么叫做文件&#xff1f;2. Linux下的路径分隔符3.在Linux中为什么会存在路径&#xf…

了解抽象思维的应用与实践

目录 一、快速了解抽象思维 &#xff08;一&#xff09;抽象思维的本质理解 &#xff08;二&#xff09;系统架构中的重要性 &#xff08;三&#xff09;软件开发中抽象的基本过程思考 意识和手段 抽象的方式 抽象层次的权衡 二、业务中的应用实践 &#xff08;一&…

百度AI布局:从财报看百度的核心竞争力和未来发展方向

百度是中国最大的搜索引擎&#xff0c;也是全球领先的人工智能&#xff08;AI&#xff09;公司。百度在2023年第三季度业绩中&#xff0c;展示了其在AI领域的强劲表现和广阔前景。 百度财报透露了关于AI业务的哪些重要信息&#xff1f; 百度在2023年第三季度的财报中&#xf…

Eclipse安装EvoSuite插件

Eclipse安装EvoSuite插件 EvoSuite自动为Java类生成JUnit测试套件,针对分支覆盖率等代码覆盖率标准。为了提高可读性,生成的单元测试被最小化,并且捕获被测试类的当前行为的回归断言被添加到测试中。 EvoSuite的GitHub地址:https://github.com/EvoSuite/evosuite 📕Ecl…

MobileNets发展与总结

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 引言MobileNetsMobileNet - V1思想代码实现 MobileNet - V2思想代码实现 MobileNet - …

flask依据现有的库表快速生成flask实体类

flask依据现有的库表快速生成flask实体类 在实际开发过程中&#xff0c;flask的sqlalchemy对应的model类写起来重复性较强&#xff0c;如果表比较多会比较繁琐&#xff0c;这个时候可以使用 flask-sqlacodegen 来快速的生成model程序或者py文件&#xff0c;以下是简单的示例&a…

人力资源管理后台 === 基础环境+登陆

目录 1.人力资源项目介绍 1.1 项目架构和解决方案 1.2 课程安排 1.3 课程具备能力 1.4 课程地址 2. 拉取项目基础代码 3.项目目录和入口文件介绍 4.App.vue根组件解析 5.基础设置settings.js和导航守卫permission.js 6.Vuex的结构 7.使用模板中的Icon图标 8.扩展…

【Python】(自定义类)计算语句执行时间

一个玩具&#xff0c;写着来玩的。 用的time模块&#xff0c;代码很简单(所以才说是个玩具) 代码&#xff1a; import time class TimeStamp:__timestampNone__keyNonedef __init__(self,tipsNone,keyNone):self.__timestamp{}self.NewStamp(tips,key)def NewStamp(self,tips,…

Python编程之魂之运算符的优先级教程

文章目录 前言优先级概述相同优先级结合性运算符优先级一览表运算符优先级重点说明结语关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资…

Windows核心编程 进程遍历与文件加密

目录 进程的遍历 CreateToolhelp32Snapshot Process32First Process32Next 文件加密 使用openssl库进行DES加密 进程的遍历 什么是快照&#xff1a;虚拟中的快照&#xff1a; 我们在分析病毒&#xff0c;分析木马的时候&#xff0c;不能在真机分析&#xff0c;在虚拟机中…

NX二次开发UF_CURVE_ask_curve_turn_angle 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_curve_turn_angle Defined in: uf_curve.h int UF_CURVE_ask_curve_turn_angle(tag_t curve, double orientation [ 3 ] , double * angle ) overview 概述 Returns …