当谈到互联网系统设计时,”三高”,即”高并发”、”高性能”和”高可用”,通常是最常听到的关键词。它们一直是互联网系统架构设计的核心主题。在前面的两节课中,我向您介绍了高并发系统设计的定义、重要性以及分层设计原则。接下来,我希望与您一起全面了解高并发系统设计的目标,然后基于这些目标,如何提升系统性能?
高并发系统设计的三大目标:高性能、高可用、可扩展
高并发指的是通过设计和优化措施,使系统能够处理更多同时发生的用户请求,也就是能够应对更大的流量负载。它是任何系统架构设计的背景和前提,因为离开了高并发性能,谈论系统的性能和可用性都是毫无意义的。显然,处理每秒一次请求和每秒一万次请求,以及在这两种不同场景下实现毫秒级响应时间和五个九(99.999%)的可用性,无论从设计的复杂性还是方案的难度来看,都存在着巨大的差异。
而性能和可用性,是我们实现高并发系统设计必须考虑的因素。
性能直接影响着用户的体验。想象一下,有两个系统都需要处理每秒一万次请求,但一个系统的响应时间只有毫秒级,而另一个系统的响应时间却是秒级的。这两个系统给用户带来的体验肯定是截然不同的。另外,可用性表示系统能够正常提供服务的时间。再做一个比喻,同样是两个承担每秒一万次请求的系统,一个可以全年无故障地持续运行,而另一个经常因维护和宕机而中断服务。如果你是用户,你会选择使用哪个系统呢?答案显而易见。性能和可用性是用户对系统的重要评价标准,它们直接关系到用户满意度和系统的成功。
另一个耳熟能详的名词叫“可扩展性”,它同样是高并发系统设计需要考虑的因素。为什么呢?
流量可以分为平常时期的正常流量和峰值时期的高流量,峰值时期的流量可能会是平时的几倍甚至几十倍。在应对峰值流量时,我们通常需要在系统架构和策略上做更多的准备工作。这就像淘宝需要花费大半年时间来为双十一做准备一样,或者微博系统在应对像“明星离婚”这样的热点事件时,尽管看起来无懈可击,但仍然可能出现服务不可用的情况。相反,易于扩展的系统能够在短时间内迅速扩展其资源,以更平稳地应对峰值流量,确保系统的可用性和性能。这种可扩展性是在处理不同流量情况下确保系统稳定运行的关键因素。
性能优化原则
“天下武功,唯快不破” 这句话也适用于系统设计中的性能。实现高性能系统是一项对程序员个人能力的巨大挑战,但在探讨实现高性能的方法之前,让我们先明确性能优化的一些基本原则。
首先,性能优化必须有针对性,不能盲目进行。这意味着性能优化应该始终以解决具体问题为导向。盲目的提前优化可能会增加系统的复杂性,浪费开发人员的时间,并且有时可能会损害业务的正常运行,因为某些优化可能会影响业务需求的平衡。
其次,性能优化遵循 “八二原则”,也就是说,你可以用 20% 的精力来解决 80% 的性能问题。因此,在优化过程中,应该集中精力解决主要的性能瓶颈。
第三,性能优化需要有数据支持。在优化过程中,你应该时刻监测和记录优化的效果,了解响应时间的改善程度以及吞吐量的提升情况。
最后,性能优化是一个持续不断的过程。高并发系统通常涉及复杂的业务逻辑,因此性能问题可能有多个方面的原因。因此,在进行性能优化时,需要明确具体的优化目标,例如,支持每秒 1 万次请求的吞吐量,并将响应时间降至 10 毫秒。然后,持续不断地寻找性能瓶颈,制定优化方案,直到达到目标为止。遵循这四个原则,并掌握常见性能问题的排查方法和优化技巧,将使您在设计高并发系统时更加得心应手。
性能的度量指标
性能优化的第三原则强调了性能指标的重要性。确切的性能指标是度量和评估性能问题以及优化效果的关键。通常情况下,我们使用系统接口的响应时间作为性能的主要指标。然而,单一的响应时间数据往往不足以提供有意义的信息,因此我们需要收集一段时间内的响应时间数据,并利用统计方法计算出一些特征值,这些特征值可以代表这段时间的性能情况。我们常用的性能特征值可以分为以下几类。
平均值
平均值的计算方法是将一段时间内的所有请求响应时间相加,然后除以总请求数。虽然平均值可以提供某种程度上的性能指标,但它对异常情况的敏感性相对较差。举例来说,假设在30秒内有10000次请求,每次请求的响应时间都是1毫秒,那么这段时间的平均响应时间也将是1毫秒。然而,如果其中100次请求的响应时间变为了100毫秒,那么整体的平均响应时间计算结果为(100 * 100 + 9900 * 1)/ 10000 = 1.99毫秒。可以看出,尽管从平均值的角度来看,只增加了不到1毫秒,但实际上有1%的请求(100/10000)的响应时间已经增加了100倍。因此,平均值在度量性能方面只能提供一个参考,不能全面反映性能的真实情况。
最大值
这个更好理解,就是这段时间内所有请求响应时间最长的值,但它的问题又在于过于敏感了。
还拿上面的例子来说,如果 10000 次请求中只有一次请求的响应时间达到 100ms,那么这段时间请求的响应耗时的最大值就是 100ms,性能损耗为原先的百分之一,这种说法明显是不准确的。
高并发下的性能优化
假如说,你现在有一个系统,这个系统中处理核心只有一个,执行的任务的响应时间都在 10ms,它的吞吐量是在每秒 100 次。那么我们如何来优化性能从而提高系统的并发能力呢?主要有两种思路:一种是提高系统的处理核心数,另一种是减少单次任务的响应时间。
1. 提高系统的处理核心数
提高系统的处理核心数是提升并行处理能力的简单途径,这可以增加系统的吞吐量。举例来说,如果系统处理核心数从一个增加到两个,并且允许两个进程在不同核心上运行,理论上系统的吞吐量可以翻倍。然而,需要注意的是,在这种情况下,吞吐量和响应时间之间的关系不再是倒数关系,而是通过公式来描述,这就是计算机领域著名的阿姆达尔定律(Amdahl’s Law)。该定律描述了并发进程数和响应时间之间的关系,考虑了任务中的串行计算量和并行计算量。
阿姆达尔定律的公式是:(Ws + Wp) / (Ws + Wp/s),其中,Ws 表示任务中的串行计算量,Wp 表示任务中的并行计算量,s 表示并行进程数。从这个公式可以得出结论,随着并行进程数的增加,加速比(性能提升)不会线性增长,而是受到串行计算量的制约。在实际情况中,当并行部分占比很小或者系统资源有限时,增加并行进程数可能不会带来明显的性能提升。
虽然增加处理核心数可以提高性能,但随着并发进程数的增加,系统资源的争用也会增加。在某个临界点上,继续增加并发进程数可能会导致系统性能下降,这被称为性能测试中的拐点模型。因此,无 并发性能问题的唯一策略,需要谨慎考虑系统资源的分配和调优。
从图中你可以发现,并发用户数处于轻压力区时,响应时间平稳,吞吐量和并发用户数线性相关。而当并发用户数处于重压力区时,系统资源利用率到达极限,吞吐量开始有下降的趋势,响应时间也会略有上升。这个时候,再对系统增加压力,系统就进入拐点区,处于超负荷状态,吞吐量下降,响应时间大幅度上升。
2.减少单次任务响应时间
要减少任务的响应时间,首先需要确定系统是CPU密集型还是I/O密集型,因为不同类型的系统有不同的性能优化策略。在CPU密集型系统中,主要的性能优化方法包括选择更高效的算法或者减少计算次数。例如,如果系统的主要任务是计算哈希值,那么选择性能更高的哈希算法可以显著提高系统性能。通常,我们可以通过性能分析工具,如Linux的perf和eBPF等,来找出消耗CPU时间最多的方法或模块,以发现潜在的性能瓶颈。
对于I/O密集型系统,大部分操作涉及等待I/O完成,其中I/O包括磁盘I/O和网络I/O。许多常见的系统,如数据库系统、缓存系统和Web系统,属于I/O密集型。性能问题可能出现在系统内部,也可能与依赖的其他系统有关。发现I/O密集型系统的性能问题的方法主要有两类。第一类是使用各种工具,Linux提供了丰富的工具集,可以用于优化性能,涵盖了网络协议栈、网卡、磁盘、文件系统、内存等。此外,某些编程语言还提供了特定于语言特性的分析工具,例如Java语言的内存分析工具。第二类方法是通过监控来发现性能问题。监控可以对任务的每个步骤进行分时统计,以找出任务中哪个步骤消耗了更多的时间。关于监控方面的内容,将在后续详细介绍。
一旦找到系统的性能瓶颈点,就需要制定相应的优化方案,具体方案将取决于问题的性质。例如,如果问题是数据库访问慢,需要检查是否存在锁表情况、是否进行全表扫描、索引是否正确使用、是否需要优化JOIN操作以及是否需要使用缓存等。如果问题与网络有关,需要检查网络参数是否需要调优,捕获数据包以查看是否存在大量超时重传,检查是否有丢包等问题。总之,性能优化需要根据不同性能问题制定不同的策略和方案,灵活应对。
原文始发于微信公众号(二进制跳动):国庆专栏-系统设计目标:如何提升系统性能?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/166975.html