一次压测引发的数据库 CPU 飙升

2024-06-21 19:52

本文主要是介绍一次压测引发的数据库 CPU 飙升,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一次压测引发的数据库CPU飙升

作者:昀鹤

一次压测过程中,当数据库的 qps 和 tps 都正常时,如果 cpu 利用率异常的高,应该如何排查?希望通过这篇文章,给你一些启发...

一、业务背景

业务需要控制频道内兑换现金的数量,于是在产品设计上给兑换现金增加了库存限制。

在此基础上形成了秒杀场景,峰值时核心接口 qps 上涨了近 600 倍(几十到几万) ,因此需要进行压测来对系统和 DB 水位摸一下高。

二、压测准备

大致分为下面几个步骤:

1)压测流量评估:就是定一下每个接口大致压测多少 qps,以及压测时到各个下游系统的流量估计。

2)压测改造:因为压测都是用的压测账户,在频道里没有历史痕迹,很多逻辑是走不到的,并且这些逻辑的不同,会直接影响到数据库和下游的流量,因此我们需要根据频道的现有数据进行链路的 mock(包括上述的流量评估也得基于这些不同链路的比例去算),举例如下:

3)测试 &发布:既然改了代码,还是得交给可爱的测试同学回归下线上链路的,当然压测的链路就可以自己测一测了,看看改造是否符合预期,hsf 控制台可以很方便的模拟影子链路:

4)下游流量报备:当然还是得跟各个下游系统知会一声的,切勿悄悄滴进村,打枪滴不要。

5)压测数据准备:主要是压测平台上的各种接口和压测流量配置(注意减去压测时的背景流量),以及压测账号申请等等(这一步也是交给测试同学)。

6)小流量预跑:在正式压测之前,大概用 1%的流量先跑一下,看看本身系统以及下游是否有异常(这一步很有必要,有时候下游系统比较复杂,可能部分场景并不能支持压测流量,提前跑一下能发现很多问题,避免正式压测的时候下游报警,然后就是👋忙🦶乱)。

三、问题出现

好了,万事具备,经过上面一系列步骤,想必本次压测一定是顺顺利利吧!

压测,启动!

====== 10%压测流量,cpu 利用率 11% ====== 挺正常

====== 30%压测流量,cpu 利用率 20% ====== 稳中向好

====== 50%压测流量,cpu 利用率 30% ====== 符合预期

====== 80%压测流量,cpu 利用率 50% ====== 感觉有点问题,但是说不出来哪里有问题!

====== 100%压测流量,cpu 利用率 80% ===== 嗯?好像不对劲?有点高

====== 100%压测流量,稳定几分钟后,突然飙到 100% ===== .....卧槽,肯定有问题,暂停压测!

唉,还是太年轻了。

赶紧排查,先拉了压测时间段的 cpu 曲线图:

看着 cpu 的监控图,我的脑海里浮现了三个疑问:

1.同等流量下,压测时的 cpu 利用率为什么高于线上实际值(线上约等于压测 80%流量时,cpu 利用率实际 40%不到,压测时已经到 60%了)?

2.流量 80%时,为什么压测流量持续不动,cpu 利用率会缓慢上涨呢?

3.流量 100%时,分明一开始 cpu 利用率还维持在 80%以下,然后突然就飙到 100%了?

总体来说,就是 CPU 高于预期。

四、问题排查

第一时间我猜测是我的压测改造不符合预期,导致打到 db 的 qps 和 tps 过高导致

急了,开始看代码,然后挑了几个压测 trace 在鹰眼上看调用,没找到问题。

然后发现我好蠢呐(主要是有点慌张),dbservice 本身就有 tps 和 qps 的监控:



看了一下,有两点,一是持续压测的时候,qps 并没有持续上涨二是差不多同流量下 qps 的值确实略高于线上实际值,但远远没有 cpu 差值这么多,所以基本可以排除一开始的猜测。



陷入了瓶颈.....



这时候我知道今天的压测指定是不行了,所以很干脆地摆了,开始安心的找问题~

4.1 发现疑点

这时候拉了 DBA 同学一起帮我们看问题,DBA 同学表示,一,数据库在长时间高压下会发生性能劣化,这也是 cpu 从 80%突然暴涨到 100%的原因(解答了第三个问题),至于 CPU 利用率异常是表象,qps 和 tps 只是其中一个影响因素,建议我们看看其他指标。

于是挨个查看数据库性能指标(带宽、慢 sql、RT....),然后终于发现了一个疑点:



这个缓慢升高的行读,非常符合压测流量 80%时 cpu 曲线的变化,很可能是问题二的原因...



那是不是也有可能是问题一的原因呢?

4.2 确认疑点

对比正常峰值流量下的行读指标

好吧,这都差了一个数量级了,基本可以确定问题出在行读异常上了



开始思考为什么行读这么多还在持续上涨,难道是同一个 sql 查出来的行数会变多

4.3 定位 sql

其实这时候心里已经隐隐约约猜到问题在哪了,但还是顺着这个行读异常排查下去



通过对比定位到了有问题的 sql



压测时:

正常时:



点进去也能看到具体的 sql 信息:



好吧,和我猜的一样,这下悬着的心终于死了。

4.4 代码分析

至于为什么同一条 sql 压测的平均行读会高这么多,还是得从代码层面来分析。



首先先看下改造逻辑和逻辑推导:

这么压测改造的原因是压测的账号是有限的(同一批压测账号重复的去轮询),如果所有账号都调过一遍接口,那后面的每次查询都能查到任务,不会再有 DB 写,为了更好的模拟线上实际情况,因此通过这种方法去让账号重新路由到注册逻辑。



然后看下任务的查询逻辑,如下:

private TaskInstanceParam createQueryParamByEffectiveTime(TaskQueryParam queryParam) {        final TaskInstanceParam dbQueryParam = new TaskInstanceParam();        Date now = TimeTravelManager.getCurrentTime(queryParam.getUserId());        dbQueryParam.createCriteria()            .andUserIdEqualTo(queryParam.getUserId())            .andBizTypeEqualTo(queryParam.getBizType())            .andTemplateIdEqualTo(queryParam.getSubBizType())            .andEffectiveStartTimeLessThanOrEqualTo(now)            .andEffectiveEndTimeGreaterThan(now);        dbQueryParam.appendOrderByClause(OrderCondition.EFFECTIVESTARTTIME, SortType.DESC);        dbQueryParam.setPagination(1, 1);        return dbQueryParam;    }

复制代码

其实就是查询符合 effectiveStartTime <= now < effectiveEndTime 的最新一条任务, 所以每次注册插入的任务,都会在下次同一账号查询时,为 sql 多加一条符合条件的行记录



至此原因已经很清晰了:随着压测的持续进行,每一个账户注册的任务条数会越来越多,因此同一条 sql 查询到的符合条件的行数会越来越多,CPU 就会花费越来越多的资源逐行处理。



后续的解法:

1)查询的时候 mock 到数据的 userId(提前准备好的线上实际来访 userId,随机取一个);

2)因为不影响查询了,所以插入逻辑不变。

五、原理刨析

接下来请 ChatGpt 老师上台,为我们普及下相关原理:

我 :什么是行读,行读高 cpu 利用率就高嘛?



我 :哦,听起来行读是比较笼统的概念,那什么是逻辑读和物理读呢,区别在哪里?



我:嗯哼,原理解释有点干燥,画个关系图(挑衅)?



我:啊?阿珍你来真的啊?



我:那总结一下,其实就是行读包括逻辑读和物理读两种,前者优于后者,平时的开发中,应该注意合理建立索引和优化 sql,来减少扫描整体行读数以及物理读的次数呗,说的对就夸一下我

六、反思

1.压测流量 80%时,就应该敏感地关注到 cpu 是高于日常水位的,其实可以避免压测调到 100%的 cpu 飙升;

2.对于 DB 的性能指标,压测时只关注了最表层的 cpu 利用率,其他的性能指标监控没有关注到位;

3.对于我们的任务场景下,查询的是有效期内的最新一条任务,实际上不太适合反复注册的压测 mock,所以在压测改造时,还需要关注改造方式与场景的匹配程度。

这篇关于一次压测引发的数据库 CPU 飙升的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082173

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中, "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时,经常听到第一范式(1NF)、第二范式(2NF)、第三范式(3NF)以及 BCNF(Boyce-Codd范式)。这些范式都旨在通过消除数据冗余和异常来优化数据库结构。然而,当我们谈到 4NF(第四范式)时,事情变得更加复杂。本文将带你深入了解 多值依赖 和 4NF,帮助你在数据库设计中消除更高级别的异常。 什么是

DM8数据库安装后配置

1 前言 在上篇文章中,我们已经成功将库装好。在安装完成后,为了能够更好地满足应用需求和保障系统的安全稳定运行,通常需要进行一些基本的配置。下面是一些常见的配置项: 数据库服务注册:默认包含14个功能模块,将这些模块注册成服务后,可以更好的启动和管理这些功能;基本的实例参数配置:契合应用场景和发挥系统的最大性能;备份:有备无患;… 2 注册实例服务 注册了实例服务后,可以使用系统服务管理,

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

开源分布式数据库中间件

转自:https://www.csdn.net/article/2015-07-16/2825228 MyCat:开源分布式数据库中间件 为什么需要MyCat? 虽然云计算时代,传统数据库存在着先天性的弊端,但是NoSQL数据库又无法将其替代。如果传统数据易于扩展,可切分,就可以避免单机(单库)的性能缺陷。 MyCat的目标就是:低成本地将现有的单机数据库和应用平滑迁移到“云”端

ORACLE 11g 创建数据库时 Enterprise Manager配置失败的解决办法 无法打开OEM的解决办法

在win7 64位系统下安装oracle11g,在使用Database configuration Assistant创建数据库时,在创建到85%的时候报错,错误如下: 解决办法: 在listener.ora中增加对BlueAeri-PC或ip地址的侦听,具体步骤如下: 1.启动Net Manager,在“监听程序”--Listener下添加一个地址,主机名写计

MyBatis 切换不同的类型数据库方案

下属案例例当前结合SpringBoot 配置进行讲解。 背景: 实现一个工程里面在部署阶段支持切换不同类型数据库支持。 方案一 数据源配置 关键代码(是什么数据库,该怎么配就怎么配) spring:datasource:name: test# 使用druid数据源type: com.alibaba.druid.pool.DruidDataSource# @需要修改 数据库连接及驱动u

CentOS下mysql数据库data目录迁移

https://my.oschina.net/u/873762/blog/180388        公司新上线一个资讯网站,独立主机,raid5,lamp架构。由于资讯网是面向小行业,初步估计一两年内访问量压力不大,故,在做服务器系统搭建的时候,只是简单分出一个独立的data区作为数据库和网站程序的专区,其他按照linux的默认分区。apache,mysql,php均使用yum安装(也尝试

Java基础回顾系列-第九天-数据库编程

Java基础回顾系列-第九天-数据库编程 数据库简介工具包java.sql API 内容与数据库建立连接执行SQL语句数据库检索和更新查询结果SQL类型对应Java类型映射元数据异常 API方法DriverManagerConnectionStatementPreparedStatementCallableStatementResultSetjava.sql.Date批处理、存储过程、事务