系统干崩了,只认代码不认人

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 为了保障系统的高可用和稳定,我发誓以后只认代码不认人。文末总结了几个小教训,希望对你有帮助。

各位朋友听我一句劝,写代码提供方法给别人调用时,不管是内部系统调用,还是外部系统调用,还是被动触发调用(比如MQ消费、回调执行等),一定要加上必要的条件校验。千万别信某些同事说的这个条件肯定会传、肯定有值、肯定不为空等等。这不,临过年了我就被坑了一波,弄了个生产事故,年终奖基本是凉了半截。

为了保障系统的高可用和稳定,我发誓以后只认代码不认人。文末总结了几个小教训,希望对你有帮助。

一、事发经过

我的业务场景是:业务A有改动时,发送MQ,然后应用自身接受到MQ后,再组合一些数据写入到Elasticsearch。以下是事发经过:

  1. 收到一个业务A的异常告警,当时的告警如下:

  2. 咋一看觉得有点奇怪,怎么会是Redis异常呢?然后自己连了下Redis没有问题,又看了下Redis集群,一切正常。所以就放过了,以为是偶然出现的网络问题。
  3. 然后技术问题群里 客服 反馈有部分用户使用异常,我警觉性的感觉到是系统出问题了。赶紧打开了系统,确实有偶发性的问题。
  4. 于是我习惯性的看了几个核心部件:
    1. 网关情况、核心业务Pod的负载情况、用户中心Pod的负载情况。
    2. Mysql的情况:内存、CPU、慢SQL、死锁、连接数等。
  5. 果然发现了慢SQL和元数据锁时间过长的情况。找到了一张大表的全表查询,数据太大,执行太慢,从而导致元数据锁持续时间太长,最终数据库连接数快被耗尽。
SELECT xxx,xxx,xxx,xxx FROM 一张大表
  1. 立马Kill掉几个慢会话之后,发现系统仍然没有完全恢复,为啥呢?现在数据库已经正常了,怎么还没完全恢复呢?又继续看了应用监控,发现用户中心的10个Pod里有2个Pod异常了,CPU和内存都爆了。难怪使用时出现偶发性的异常呢。于是赶紧重启Pod,先把应用恢复。
  2. 问题找到了,接下来就继续排查为什么用户中心的Pod挂掉了。从以下几个怀疑点开始分析:
    1. 同步数据到Elasticsearch的代码是不是有问题,怎么会出现连不上Redis的情况呢?
    2. 会不会是异常过多,导致发送异常告警消息的线程池队列满了,然后就OOM?
    3. 哪里会对那张业务A的大表做不带条件的全表查询呢?
  3. 继续排查怀疑点a,刚开始以为:是拿不到Redis链接,导致异常进到了线程池队列,然后队列撑爆,导致OOM了。按照这个设想,修改了代码,升级,继续观察,依旧出现同样的慢SQL 和 用户中心被干爆的情况。因为没有异常了,所以怀疑点b也可以被排除了。
  4. 此时基本可以肯定是怀疑点c了,是哪里调用了业务A的大表的全表查询,然后导致用户中心的内存过大,JVM来不及回收,然后直接干爆了CPU。同时也是因为全表数据太大,导致查询时的元数据锁时间过长造成了连接不能够及时释放,最终几乎被耗尽。
  5. 于是修改了查询业务A的大表必要校验条件,重新部署上线观察。最终定位出了问题。

二、问题的原因

因为在变更业务B表时,需要发送MQ消息( 同步业务A表的数据到ES),接受到MQ消息后,查询业务A表相关连的数据,然后同步数据到Elasticsearch。

但是变更业务B表时,没有传业务A表需要的必要条件,同时我也没有校验必要条件,从而导致了对业务A的大表的全表扫描。因为:

某些同事说,“这个条件肯定会传、肯定有值、肯定不为空...”,结果我真信了他!!!

由于业务B表当时变更频繁,发出和消费的MQ消息较多,触发了更多的业务A的大表全表扫描,进而导致了更多的Mysql元数据锁时间过长,最终连接数消耗过多。

同时每次都是把业务A的大表查询的结果返回到用户中心的内存中,从而触发了JVM垃圾回收,但是又回收不了,最终内存和CPU都被干爆了。

至于Redis拿不到连接的异常也只是个烟雾弹,因为发送和消费的MQ事件太多,瞬时间有少部分线程确实拿不到Redis连接。

最终我在消费MQ事件处的代码里增加了条件校验,同时也在查询业务A表处也增加了的必要条件校验,重新部署上线,问题解决。

三、总结教训

经过此事,我也总结了一些教训,与君共勉:

  1. 时刻警惕线上问题,一旦出现问题,千万不能放过,赶紧排查。不要再去怀疑网络抖动问题,大部分的问题,都跟网络无关。
  2. 业务大表自身要做好保护意识,查询处一定要增加必须条件校验。
  3. 消费MQ消息时,一定要做必要条件校验,不要相信任何信息来源。
  4. 千万别信某些同事说,“这个条件肯定会传、肯定有值、肯定不为空”等等。为了保障系统的高可用和稳定,咱们只认代码不认人
  5. 一般出现问题时的排查顺序:
    1. 数据库的CPU、死锁、慢SQL。
    2. 应用的网关和核心部件的CPU、内存、日志。
  6. 业务的可观测性和告警必不可少,而且必须要全面,这样才能更快的发现问题和解决问题。

======>>>>>> 关于我 <<<<<<======

本篇完结!欢迎点赞 关注 收藏!!!

原文链接https://mp.weixin.qq.com/s/TvIpTZq0XO8v9ccYSsM37Q

相关文章
|
算法 分布式数据库
Paxos算法:分布式一致性的基石
【4月更文挑战第21天】Paxos算法是分布式一致性基础,由Leslie Lamport提出,包含准备和提交阶段,保证安全性和活性。通过提案编号、接受者和学习者实现,广泛应用于分布式数据库、锁和配置管理。其简单、高效、容错性强,影响了后续如Raft等算法,是理解分布式系统一致性关键。
|
7月前
|
存储 缓存 中间件
中间件对 Pinia 状态管理的性能有什么影响?
中间件对 Pinia 状态管理的性能有什么影响?
208 65
|
6月前
|
人工智能 供应链 Cloud Native
中国AI编码工具崛起:技术突围、生态重构与开发者新范式
中国AI编码工具如通义灵码、百度Comate等,正从西方产品的主导中突围。通过大模型精调、中文友好型理解及云原生赋能,构建差异化优势。这些工具不仅提升效率,还推动中国软件产业从使用者向标准制定者转变。然而,技术原创性、生态碎片化和开发者信任危机仍是挑战。未来目标不是取代现有工具,而是定义适合中国开发者的智能编码新范式。
347 24
|
9月前
|
SQL Java API
|
安全 新能源 知识图谱
固态电池:电动汽车的能源革新
【10月更文挑战第15天】固态电池凭借其高能量密度、长续航、卓越安全性和快速充电等优势,正引领新能源汽车领域的技术革命。本文详细探讨了固态电池的技术特点、优势及其对电动汽车产业的影响,展示了其在提升续航里程、增强安全性和降低成本方面的巨大潜力。随着技术的不断进步和成本的降低,固态电池有望成为推动电动汽车行业发展的关键力量,开启一个更加绿色高效的交通新时代。
|
JSON API 数据格式
Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用
Django REST framework序列化器详解:普通序列化器与模型序列化器的选择与运用
|
数据采集 SQL DataWorks
【颠覆想象的数据巨匠】DataWorks——远超Excel的全能数据集成与管理平台:一场电商数据蜕变之旅的大揭秘!
【8月更文挑战第7天】随着大数据技术的发展,企业对数据处理的需求日益增长。DataWorks作为阿里云提供的数据集成与管理平台,为企业提供从数据采集、清洗、加工到应用的一站式解决方案。不同于桌面级工具如Excel,DataWorks具备强大的数据处理能力和丰富的功能集,支持大规模数据处理任务。本文通过电商平台案例,展示了如何使用DataWorks构建数据处理流程,包括多源数据接入、SQL任务实现数据采集、数据清洗加工以提高质量,以及利用分析工具挖掘数据价值的过程。这不仅凸显了DataWorks在大数据处理中的核心功能与优势,还展示了其相较于传统工具的高扩展性和灵活性。
362 0
|
机器学习/深度学习 人工智能 自然语言处理
利用深度学习提升语音识别准确率的技术探讨
传统的语音识别技术在面对复杂的语音场景时常常表现出准确率不高的问题。本文探讨了如何利用深度学习技术,特别是深度神经网络,来提升语音识别的精度。通过分析深度学习在语音处理中的应用以及优势,我们展示了如何结合最新的研究成果和算法来解决现有技术的局限性,进一步推动语音识别技术的发展。 【7月更文挑战第3天】
879 0