容易引起雪崩的两个处理

简介: 容易引起雪崩的两个处理

背景


先介绍标题《容易引起雪崩的两个处理》的第一个处理:慢查询。上周在测试环境遇到一个慢查询问题,虽然是测试环境,但是现象还是很让人担忧的:“在大量执行update操作”“已经执行1个多小时”“负载200多,基本上库都卡死了”。把库都要搞挂了,细思极恐啊。于是,这个事件处理的优先级即刻被升级为S级别,我们进行了点线面的梳理和分析。



现象分析


首先针对此问题做一个分析。慢查询的原因简单可以这么理解:公司创立之初写的代码,当时上线工期紧,做的比较糙(声明:不代表公司水平)。后台有个人工查询操作,这个操作要查询下游,下游是异步返回结果。所以是通过异步转同步实现的,使用了一张表,每次操作将历史记录标识位全部改成“已过期”,再将新结果插入到数据表中。“在大量执行update操作”指的就是批量更新标识位的操作。大概一次操作要更新几十万条,然后插入几条。一次更新要执行几十秒。


问题解决


当时同事提出要加索引解决,我第一个反应:最主要的字段只有两个值:“已过期”、“未过期”。对这种字段加索引是不是没什么用?结果实际测试结果是:不加这条索引十几秒执行完的查询和更新操作,加了索引只要几毫秒。


原理分析


这里主要分析三个问题。


1>为什么这条索引如此管用?


先说说为什么我第一反应觉得不管用,看看某乎上的神回复:


1112728-20211002101531703-790099193.png


先说为什么能提高查询速度。举个例子,假设表中有一千万条记录,状态字段有0和1两个值。某个状态为0的记录总数大概会有100条,那么你想查询状态为0的记录时,有没有索引影响非常大,而查询状态为1的记录,则索引基本无用。如果两种状态的记录数相差无几的话,索引也基本无用。所有的关于索引的文章,建议你不要为这种字段建索引的依据,都是以值分布是均匀为前提的。但如果值分布不均匀的时候,这个建议就不一定是正确的了。当我们需要查询的记录恰好是分布较少的记录的时候,值分布越是不均匀,索引就越有价值!那为什么能提高更新速度呢?


对于update/insert/delete的每次执行,字段的索引都必须重新计算更新。听起来很慢,但是更新操作实际上是先select再update的过程,这里因为“未过期”数据条数很少,所以select效率高,然后更新是按照id进行更新,所以很快。


2>为什么慢查询会导致库卡死?


一般慢查询,特别是这样将历史记录标识位全部改成“已过期”的,必然会引起锁表。这个表的相关操作会受到影响是可以理解的,但是为什么会影响到整个数据库呢?这就涉及一个最基本的问题:资源竞争。慢查询和慢请求一个道理,长时间占用连接不释放、连接数是有限的,其他后到的请求要排队。


这个问题在生产环境相对好些,因为生产环境一般都会用物理机,而且数据盘至少是SSD的。测试环境资源差很多,所以问题会更明显。


3>负载200多是什么概念?


系统平均负载(load averages)是对当前CPU工作量的度量,被定义为特定时间间隔内运行队列中的平均线程数。可以通过top, htop, uptime这些命令找到它们.关于负载的含义,网上最广泛的示例,是通过桥梁的通过率来解释的。讲的真心好,所以直接「借鉴」过来,需要看原文的直接从参考引用处自行穿越。注意这里的比喻是基于单核CPU的。


系统负荷为0,意味着大桥上一辆车也没有

系统负荷为0.5,意味着大桥一半的路段有车

系统负荷为1.0,意味着大桥的所有路段都有车,但任然可以顺次通行

系统负荷为1.7,除了桥满之外,在桥的入口处还有70%的车辆在等待


系统负荷为200,除了桥满之外,在桥的入口处还有19900%的车辆在等待!不卡死才怪!

 

线


sql问题影响巨大,所以我们针对所有的数据表进行了梳理,排查隐患。

 


还需要梳理所有可能引起稳定性隐患的问题。这里就要引出标题《容易引起雪崩的两个处理》的第二个处理了:递归。


递归如果深度控制不好,会产生栈溢出,也就是StackOverflowError。溢出而使得有用的存储单元被改写,往往会引发不可预料的后果。怎么改呢?要解决这个问题之前刷的leetcode技能就排上用场了。把递归算法转化为非递归算法有如下三种基本方法


1、对于尾递归和单向递归的算法,可以用循环结构的算法替代


2、自己用堆栈模拟运行时栈,分析只保存必须保存的信息(因而可小幅提高时间效率),从而用非递归算法替代递归算法。


3、利用堆栈保存参数,由于堆栈的后进先出特性吻合递归算法的执行过程,因而可以用非递归算法替代递

 

后记


89年有个电影版的《红楼梦》,演员阵容豪华让人咋舌。赵丽蓉演的刘姥姥、刘晓庆演的王熙凤、傅艺伟演的薛宝钗……。很小就觉得经典电视剧版的《红楼梦》里薛宝钗优雅端庄,颇有大家闺秀之风。看到了电影版《红楼梦》,特别是有个名场面:宝玉管宝姐姐要她随身挂在脖子上的金锁来看:电视剧版的宝姐姐金锁是挂在贴身内层的,当时宝姐姐是这样的:宝姐姐脸微红,转过身去解下金锁,又缓缓转过来身来,微微笑着给了宝玉。电影版的宝姐姐也是金锁是挂在贴身内层的,宝姐姐听宝玉问他要,她不假思索、干脆利落的解下来给了宝玉。我看到这里,心里的表情是这样的:


1112728-20211002101641892-285607446.png


这是哪里来的英姿飒爽的女侠走错了片场?


而在实际工作,我也经常会遇到类似的反差。咱们的每个软件设计和代码,周围的人,后来的人内心都自有评价。愿他们看到的是最好的我们。


相关文章
|
SQL 安全 关系型数据库
Sqlmap2021 -- Referer注入
Sqlmap2021 -- Referer注入
310 1
|
6月前
|
Prometheus 监控 Cloud Native
Prometheus配置docker采集器
本文介绍了如何使用 Prometheus 监控 Docker 容器,涵盖环境准备、配置文件编写及服务启动等步骤。首先确保安装 Docker 和 Docker Compose,接着通过 `docker-compose.yml` 配置 Prometheus 和示例应用。创建 `prometheus.yml` 指定数据采集目标,最后用 `docker-compose up -d` 启动服务。文章还展示了甘特图和类图,帮助理解服务状态与关系,助力提升系统可靠性和可维护性。
201 11
|
5月前
|
存储 网络协议 数据安全/隐私保护
SMTP/POP3/IMAP(电子邮件协议)
本文介绍了电子邮件系统中常用的三种协议:SMTP、POP3 和 IMAP。SMTP(简单邮件传输协议)用于发送邮件,设计简单且广泛支持;POP3(邮局协议版本3)用于接收邮件,适合离线使用但不支持文件夹管理;IMAP(互联网消息访问协议)允许用户在服务器上管理邮件,支持多设备同步和部分下载。文章还对比了这三种协议的功能、端口及特点,并分析了它们在实际场景中的应用,帮助用户根据需求选择合适的协议。
1884 24
|
6月前
|
JSON 前端开发 Java
深入理解 Spring Boot 中日期时间格式化:@DateTimeFormat 与 @JsonFormat 完整实践
在 Spring Boot 开发中,处理前后端日期交互是一个常见问题。本文通过 **@DateTimeFormat** 和 **@JsonFormat** 两个注解,详细讲解了如何解析前端传来的日期字符串以及以指定格式返回日期数据。文章从实际案例出发,结合代码演示两者的使用场景与注意事项,解决解析失败、时区偏差等问题,并提供全局配置与局部注解的实践经验。帮助开发者高效应对日期时间格式化需求,提升开发效率。
1646 2
|
10月前
|
API 索引
鸿蒙开发:实现一个超简单的网格拖拽
实现拖拽,最重要的三个方法就是,打开编辑状态editMode,实现onItemDragStart和onItemDrop,设置拖拽移动动画和交换数据,如果想到开启补位动画,还需要实现supportAnimation方法。
268 13
鸿蒙开发:实现一个超简单的网格拖拽
|
8月前
2024阿里云技术年报 基础设施篇
2024阿里云技术年报 基础设施篇
179 11
|
监控 Unix Java
使用Nohup命令管理后台进程的实用技巧
使用Nohup命令管理后台进程的实用技巧
|
前端开发 测试技术 持续交付
git commit 提交规范
git commit 提交规范
630 0
|
编解码 光互联 虚拟化
虚幻引擎 5 来了!不止 Lumen、Nanite 新技术,性能及 UI 均迎来大升级
虚幻引擎 5 来了!不止 Lumen、Nanite 新技术,性能及 UI 均迎来大升级
561 0
虚幻引擎 5 来了!不止 Lumen、Nanite 新技术,性能及 UI 均迎来大升级