0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一个update语句执行要10s,大厂的架构真无语!

jf_ro2CN3Fa 来源:芋道源码 2023-01-29 10:45 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群


一、问题描述

2022年7月2x日,窗外夕阳将落不落,余晖洒落在街道上,远处的热浪仿佛在说:嘿,欢迎来到烤箱中的瑞士卷—成都!

“嘿!”,我回过神来看到一只洁白纤细的手落在我的肩膀上,眼光从窗外收回顺着手臂快速扭跟过去,然后看到脸色暗淡夹杂着些许痘痘的测试妹纸一脸的严肃!“昨天晚上上线后,这个后台执行更新信息非常缓慢,这里肯定有问题!”

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

二、问题分析

“好的,我排查一下”。三步并作两步回到工位,掀开MacBook Pro的盖子、打开显示器的电源、输入链路日志跟踪系统地址、复制traceId、查看日志…… 这一套操作熟悉得令人心疼。

排查日志初步发现实际调用了两次,第一次执行时间接近10s,调用超时,第二次执行时间接近5s。你肯定也想到了,RPC调用retry设置了值。对RPC配置检查之后确实设置的是retry=1,实际项目中,增、删、改等操作不应设置retry。

通过调用链排查发现update执行非常耗时。聪明的你一定也第一时间怀疑update语句有性能问题。把update语句拿出来:

updatetableseta=#{1},b=#{2},...whereid=#{0}(id主键)

这下傻眼了,根据主键id更新怎么可能要执行10s?

masaga?!!

为了验证我的猜想,command + 空格、键入idea并回车、打开对应的工程、定位到对应的方法处、迅速浏览一遍并思索片刻之后,真相大白!

06f25d70-9f73-11ed-bfe3-dac502259ad0.jpg

服务B执行完update语句之后,事务commit之前,还有两个异步通知任务,使用的是spring的@Async注解,自定义的线程池,跟踪日志中的线程标志,排查过程中发现有的异步任务居然由原线程执行!进一步分析日志发现这种现象并不是一直发生,有时又是由异步线程执行。开始排查线程池,线程池果然设置了callRunner的失败策略。

所以,由原线程执行时,事务的范围如下:

06fe1174-9f73-11ed-bfe3-dac502259ad0.jpg

定位到原因之后,修改线程池参数为常见策略,初始和最大线程数相同,队列数9999,保证线程池的线程充足性。

修复

灰度

招呼测试妹纸测试

自信满满,悠闲喝水

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

三、梅开二度

“在高并发场景下,复现了这个问题,你快看一下”!测试妹纸对我投来鄙视的眼光犀利的说道:“修复好了,再喊我回归哈,拜拜~”。

奇怪,为什么这么平常的一个update语句,怎么会执行这么长时间呢?难道出发了框架的bug导致事务提交延迟?不对不对,这个方向想偏了~也没有其他地方在更新这个表了呀?不可能有表锁,更不可能有行锁呀……

masaga?!!

根据表锁以及行锁的思路,为了验证我的内心OS猜想,立即使用 show processlist 进行了连接查询,果然有重大发现,除了服务B有连接之外,还有服务A的连接。而服务A又是服务B的上游系统!系统架构如下:

070c7a52-9f73-11ed-bfe3-dac502259ad0.jpg

执行顺序如下:

顺序 服务 执行动作 关键点
1 服务A 执行update语句 数据库 行锁 lock
2 服务A 调用服务B RPC 调用
3 服务B 执行update语句 数据库 行锁 waiting
4 服务A 调用服务B超时 RPC timeout
5 服务A 再次调用服务B RPC retry
6 服务A 调用调用服务B再次超时 RPC timeout
7 服务A PRC调用超时异常 数据库 事务回滚 行锁 unlock
8 服务B 执行 数据库 行锁 竞争

不被人信任的滋味很难受!为了重新赢回测试妹纸对我的信任,这次的bug修复只需成功不许失败!

四、解决方案

知道病根之后,问题就很简单了。

最理想的方案

对微服务架构进行重构,但这样做带来的收益不高,现在手上还有优先级更高的事情要做。

07185eda-9f73-11ed-bfe3-dac502259ad0.jpg
最实际的方案

是将服务A对服务B的调用和服务A的事务分离出来。这样就不存在锁竞争的问题了。

072741ca-9f73-11ed-bfe3-dac502259ad0.jpg

五、总结

看到了这里,你心里是不是已经在想:我靠,大厂的系统架构真的很垃圾,我都是关着灯的~(走错片场~)

其实这个系统变成这样是有历史原因的,如果当初的开发者能够采用DDD的思想或者能够明白微服务的对象高内聚思想,或许今天就不会发生在我身上这场研发与测试之间的信任危机。

夕阳落下,夜晚笼罩着大地。路旁的小猫咪悠然站了起来,张大嘴巴打个哈欠的同时伸了个懒腰,然后走向3号门口,等待着心地善良的加班儿投食猫粮。“验证通过,早点下班”。不远处传来测试妹纸的声音,夹杂着中央空调吹出的风声。



审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • macbook
    +关注

    关注

    0

    文章

    500

    浏览量

    42767
  • 线程
    +关注

    关注

    0

    文章

    508

    浏览量

    20759
  • 系统架构
    +关注

    关注

    1

    文章

    72

    浏览量

    24128

原文标题:一个update语句执行要10s,大厂的架构真垃圾!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    蓝牙中心设备,同时连接10外设,通信带宽能达到20k/s

    经典蓝牙(1.2/2.0+EDR)速率 1-3Mbps,主从架构最多连 7 从设备约 80kbps(10KB/s)以上仅支持最多 7
    发表于 11-17 15:48

    使用evn工具执行pkgs --update时出现如下报错,怎么解决?

    # pkgs --update [Use Github server - auto decision based on IP location] fatal: destination path
    发表于 09-19 08:02

    ubuntu 22.04 执行pkgs--update 失败的原因?

    ubuntu 22.04 使用pkgs —update 失败,我的源码是从gitee , git 是可以正常使用的
    发表于 09-15 06:09

    env装好了,执行scons的时候,报错是哪里的问题?

    or external command, operable program or batch file. 然后执行menuconfig -s,继续报错: Traceback (most recent
    发表于 09-11 06:09

    红魔10S Pro+体验报告

    深耕专业电竞领域多年,红魔始终以硬核性能和前沿配置拓宽移动游戏体验的边界。不久前推出的红魔10S Pro+搭载性能增强的骁龙 8至尊版移动平台,实现了性能与能效的大幅提升,并在AI游戏体验上带来重磅
    的头像 发表于 08-08 16:59 1954次阅读

    Unicore标准NEMA语句GSA及说明

    本文介绍和芯星通的NEMA语句说明。
    的头像 发表于 07-16 11:39 485次阅读
    Unicore标准NEMA<b class='flag-5'>语句</b>GSA及说明

    在使用EZ-USB® FX3™ 设备时,上电后相机开始正常工作,但延时10s左右播放器才能够显示图像数据?为什么?

    在使用EZ-USB® FX3™ 设备时,上电后相机开始正常工作,但延时10s左右播放器才能够显示图像数据?这是由于固件中的某些设置问题吗?
    发表于 07-16 07:08

    驱动下代E/E架构的神经脉络进化—10BASE-T1S

    随着“中央+区域”架构的演进,10BASE-T1S凭借其独特优势,将成为驱动下代汽车电子电气(E/E)架构“神经系统”进化的关键技术。
    的头像 发表于 07-08 18:17 797次阅读
    驱动下<b class='flag-5'>一</b>代E/E<b class='flag-5'>架构</b>的神经脉络进化—<b class='flag-5'>10BASE-T1S</b>

    基础篇3:掌握Python中的条件语句与循环

    块 else: # 所有前面的条件表达式都为假时执行的代码块 示例 以下是简单的示例,演示了如何使用条件语句来决定是否打印不同的消息: 复制代码 age = 18 if ag
    发表于 07-03 16:13

    浅谈wsl --update` 命令行选项无效的解决方案

    PS C:\Users\Administrator> wsl --update >> 命令行选项无效: --update
    的头像 发表于 06-27 10:28 9848次阅读

    《ESP32S3 Arduino开发指南》第三章 C/C++语言基础

    访问数组中的某个元素,则需要使用以下语句。数组名称[下标] 需要注意的是,数组下标是从0开始编号的。例如,将数组a中的第一个元素赋值为
    发表于 06-10 09:20

    详解TIA Portal SCL编程语言中的IF语句

    IF 语句是编程中最基本和最重要的控制结构之,它的主要作用是根据条件决定程序的执行路径,IF 语句是编程中实现逻辑判断和决策的基础。
    的头像 发表于 05-24 15:01 1440次阅读
    详解TIA Portal SCL编程语言中的IF<b class='flag-5'>语句</b>

    hrtim里update reset和reset update同时打开不会互相激励吗?

    hrtim里update reset和reset update同时打开不会互相激励吗,另外为什么现在定时器周期值不用-1了
    发表于 04-27 08:57

    CPU的各种指令和执行流程

    、数据传输等功能。深入理解CPU的指令,我们需要从多个维度进行分析,尤其是指令的构成、分类、执行流程以及与不同架构的关系。
    的头像 发表于 04-18 11:24 1922次阅读

    ADC128S022的驱动架构参考 ti-adc128s052.c,如何做移位生成12bit结果呢?

    ADC128S022的驱动架构参考 ti-adc128s052.c, 具体如下图所示。 上层读取buf[1], buf[2]请问如何做移位生成12bit结果呢?
    发表于 12-16 06:32