0

从CPU100%高危故障到稳定在10%:一个月的优化之旅,成功上线! - 努力的小雨

 7 months ago
source link: https://www.cnblogs.com/guoxiaoyu/p/17928968.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

从CPU100%高危故障到稳定在10%:一个月的优化之旅,成功上线!

经过三个月的开发,项目通过了所有测试并上线,然而,我们发现项目的首页几乎无法打开,后台一直发生超时错误,导致CPU过度负荷。在这次项目开发过程中,我制定了一份详细的技术优化方案。考虑到客户无法提供机器硬件配置,我们只能从软件方面寻找解决方案,以满足客户的预期。同时,我还准备了一个简单的项目复盘,如果你对此感兴趣,也可以一起查看。

image

在进行第一次优化时,我们发现SQL的基本书写存在问题。通过使用pinpoint工具,我们成功抓取了所有的SQL语句。然后,我们请一位对业务非常熟悉的人对所有的SQL进行了审查,主要是优化SQL书写中的基本错误。由于开发人员的疏忽,导致了数据库的全表查询,但是由于测试数据库的数据量不足,测试环境并没有发现潜在的基础SQL问题。经过第一轮SQL优化,现在所有的SQL语句已经得到了正确的修正。

经过压力测试后,我们发现数据库的CPU已经超负荷运行。为了进一步优化性能,我们决定进行SQL的详细优化。在查询表关联的过程中,我们发现有很多字段实际上已经在业务表中冗余存在,因此无需再去关联另外一张表。通过减少表的关联操作,我们可以有效提高SQL的执行效率。

由于测试数据量不足且业务关联性较差,我们需要申请将正式数据库中涉及的表数据迁移至测试数据库,以模拟正式环境进行压力测试。

经过初步讨论,我们认为业务表的数据量很大可能导致了SQL查询的缓慢和CPU性能的占用。为了优化这个问题,我们决定根据所有报表涉及的表及其字段,扫描业务增量数据并抽离出一个小表用于报表业务查询。

在进行数据迁移的过程中,我们要注意的是,除非数据量很小的表,不要直接将其抽离到小表中。相反,我们需要引入一个中间表来提前缓冲数据。如果直接去除中间表,可能会导致对业务表的锁定,从而降低业务操作的性能。

注意点:在上线之前,务必确保准备好初始化表数据和相应的表索引。丢失一个都会导致生产数据库的CPU跑满。

image

由于项目需要进行时间范围查询,当选择以月为单位时,首页在压测并发下未能达到预期要求。因此,我们进行了方案升级,引入了结果表的概念。具体而言,我们按照月份的最小统计范围提前生成结果统计表。也有人提出在此阶段涉及到的业务接口中加入一步更新结果表中的某一个指标字段的操作。然而,这样做会导致业务之间的耦合性非常严重,可能随时影响正常业务的操作。

在中期之前,我们已经想到了使用中间表->小表的方式来进行数据处理。因此,我们能够准确地了解当前数据的变化情况,并根据变动的字段值进行相应的操作,对相关的指标字段进行增加或减少的操作。

为了解决由于多个小表同时更新统计表字段而导致的行锁问题,我们采取了进一步的优化措施,将原统计表拆分为两张表,但仍保持主键一致。这样做的好处是减少了不同小表同时更新同一行数据的情况,但需要注意的是指标字段是有所不同的。

虽然此时也满足了压测要求,但是仍然需要考虑到此项目报表的风险会影响到业务数据库的正常操作,所以将其切换到另外一个小型数据库来专门提供其查询。就算出现问题也不会影响到业务端的正常操作。

注意点:在进行当月上线之前,需要提前对统计表的各个指标进行初始化。这样可以确保数据的准确性和完整性。

经过上一期的系统优化,我们成功满足了预期的压力测试结果,所有按钮和报表功能均可以正常点击和查看。值得一提的是,数据库的CPU性能一直保持在10%以下,显示了良好的稳定性。

image

说明:有毛刺现象是因为这个小型数据库在进行同步大表数据导致的。其实,关于结果集这种方法,在前期已经有过提出,但是我当时选择了放弃,因为存在许多不确定性因素,可能导致指标值和实际值有一定的差异。然而,目前来看,至少可以满足压测和使用的要求。

以上只是我在技术方面的参与和优化过程的简要描述。接下来,我将作为一个非程序员身份来对整个项目进行一个简单复盘,从一开始的项目参与到需求统计指标的制定,我一直都在其中参与,并且对这个模块非常熟悉。当第三方提出无法实现或者实现上存在困难的问题时,我通常会举例说明,因为第三方并不会像程序员一样从技术角度考虑问题。在我看来,到目前为止,一切都没有问题,因为我们已经仔细审查了每个指标,确定了哪些问题需要第三方进一步研究。

下一步就有问题了,整个项目的需求我是最了解的,但是由于我并不参与项目的开发,导致项目经理对于某一个小点根本不了解。因此,其他人经常来找我咨询,并且直到项目接近尾声时,当意识到无法满足客户的要求,才急忙找我参与开发。这是其中一个存在的问题。

让我来详细说明一下我的问题。在整个开发过程中,我的问题也逐渐显露出来,那就是为什么只有我一个人了解这个问题,而其他人却一无所知呢?原因是因为我一直在负责这个模块的开发,但是我并没有将相关的细节文档化,导致所有的细节都只存在于我的脑海中。因此,其他人只能不断地向我请教,才有可能了解这些细节。然而,这种依赖性是需要避免的,尽管我自己也很不喜欢写文档。

在项目中期时,我听到最多的抱怨之一是关于指标统计的问题。有些指标统计了多一个数,而其他指标则统计了少一个数。尽管开发工作基本上已经完成,但在核对各个数字时却出现了问题。然而,直到后期才发现这些问题其实是由于SQL编写不当所导致的。在对数据库进行操作时,我们可能没有考虑到一些边界情况或者特殊情况,导致了数据统计的不准确性。另外,还有可能是测试数据库中的数据基本都是脏数据,也就是不符合我们预期的数据,这也对统计结果造成了一定的影响。

image

在项目的后期阶段,由于排期已经到达客户可接受的最低底线,大家都非常着急地制定优化方案。这时候我才被真正拉过来参与,整个过程耗时将近一个月,没有休息的时间。出方案的人也开始费尽心思地想办法,但前提是他们对业务一无所知。他们也没有花时间静下心来好好思考,只管出方案,而我们这边需要再评估一下。我们花了整整一天(24小时)的时间来进行评估,具体方案和技术优化的细节我就不详细介绍了,总之最终的方案就是我之前提到的各种技术优化。

其实,我在这个过程中发现了一个规律,前期一直在进行指标分析,而后期的重点则是确保系统能够满足压力测试的要求,即客户的预期。如果下次你有类似的需求,一定要确保在系统正常运行的基础上,再去优化指标的准确性,就像这次项目,当初上线时连页面都无法打开,数据库的CPU直接达到了极限,根本没有时间去核对报表指标了。简而言之,我们需要先满足最低要求,然后逐步进行优化。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK