一次生产事故的优化经历
一次生产事故的优化经历事故起因凌晨三点的告警那是一个寻常的周三凌晨我的手机突然疯狂震动——生产环境的告警系统连续发出了十多条P0级告警。打开监控面板我看到一个刺眼的数字用户登录接口的响应时间从平均200ms飙升到了15秒错误率从0.1%暴涨到30%。更糟糕的是这个接口是所有业务入口它的宕机意味着整个平台无法使用。我立刻登录服务器发现CPU使用率接近100%内存占用也在持续攀升。初步定位问题出在一个最近上线的“用户画像聚合”功能上。这个功能会在用户登录时从多个微服务拉取数据然后合并成一个包含用户标签、行为记录、推荐策略的复杂对象。## 初步排查SQL查询的灾难通过分析APM应用性能管理工具我发现罪魁祸首是一个看似无害的SQL查询。该查询用于获取用户的“最近浏览记录”但它在生产环境下面对百万级用户数据时表现出了惊人的性能问题。### 原始的慢查询代码python# user_service.py - 原始版本性能灾难import psycopg2from datetime import datetime, timedeltadef get_user_browsing_history(user_id: int, limit: int 50): 获取用户最近浏览记录 问题未使用索引且查询范围过大 conn psycopg2.connect( hostdb-prod, dbnameanalytics, userapp_user, passwordsecret ) cursor conn.cursor() # 致命错误1使用LIKE模糊查询用户ID本应是精确匹配 # 致命错误2未限制时间范围导致扫描全表 query SELECT product_id, view_time, category FROM browsing_history WHERE user_id LIKE %{}% -- 模糊匹配无法使用索引 AND view_time {} -- 硬编码30天前但未使用参数化 ORDER BY view_time DESC LIMIT {} .format(user_id, (datetime.now() - timedelta(days30)).isoformat(), limit) cursor.execute(query) results cursor.fetchall() cursor.close() conn.close() return results这段代码存在三个致命问题1.模糊查询LIKE %{}%导致数据库无法使用B-tree索引必须全表扫描。2.未参数化查询字符串格式化拼接SQL不仅带来SQL注入风险还让数据库无法缓存执行计划。3.无谓的全表扫描即使只有100个活跃用户每次查询也要扫描数百万行历史记录。## 第一次优化索引与参数化我立刻修改了代码并添加了数据库索引。但此时告警仍在持续——虽然单个查询快了但并发量太大数据库连接池被耗尽。### 优化后的代码python# user_service.py - 第一次优化解决SQL问题import psycopg2from psycopg2 import poolfrom datetime import datetime, timedelta# 使用连接池避免频繁创建连接connection_pool psycopg2.pool.SimpleConnectionPool( 1, 20, # 最小1个连接最大20个 hostdb-prod, dbnameanalytics, userapp_user, passwordsecret)def get_user_browsing_history_optimized(user_id: int, limit: int 50): 优化版本使用参数化查询和精确匹配 同时需要数据库添加复合索引 (user_id, view_time DESC) conn connection_pool.getconn() try: cursor conn.cursor() # 使用参数化查询避免SQL注入且数据库可缓存执行计划 # 精确匹配user_id利用索引 # 限制时间范围减少扫描行数 query SELECT product_id, view_time, category FROM browsing_history WHERE user_id %s -- 精确匹配使用索引 AND view_time %s -- 参数化时间范围 ORDER BY view_time DESC LIMIT %s # 只查询最近7天的数据而不是30天 seven_days_ago datetime.now() - timedelta(days7) cursor.execute(query, (user_id, seven_days_ago, limit)) results cursor.fetchall() return results finally: # 释放连接回连接池 cursor.close() connection_pool.putconn(conn)同时我在数据库执行了以下索引创建sqlCREATE INDEX CONCURRENTLY idx_user_view_time ON browsing_history (user_id, view_time DESC);## 深入分析缓存与熔断的缺失SQL优化后单次查询耗时从15秒降到50ms但问题仍未完全解决。通过分析日志我发现这个“用户画像聚合”函数在高峰时期会被并发调用上千次。即使每个调用只花50ms上千次并发也会耗尽数据库连接池导致大量请求排队超时。更严重的是这个函数没有任何缓存机制每次用户刷新页面都要重新计算。而且当数据库压力过大时没有熔断机制导致雪崩效应。### 重构引入缓存与熔断python# user_profile_aggregator.py - 重构版本缓存熔断import redisimport jsonfrom datetime import datetime, timedeltafrom functools import lru_cachefrom typing import Optionalclass UserProfileAggregator: 用户画像聚合器 使用多级缓存本地缓存LRU 分布式缓存Redis 并实现熔断保护 def __init__(self, redis_client: redis.Redis): self.redis redis_client # 本地缓存最多缓存1000个用户5分钟过期 self.local_cache lru_cache(maxsize1000) # 熔断器状态 self.circuit_breaker_state { failure_count: 0, last_failure_time: None, is_open: False } self.CIRCUIT_BREAKER_THRESHOLD 5 # 连续5次失败则熔断 self.CIRCUIT_BREAKER_TIMEOUT 30 # 熔断持续30秒 def get_user_profile(self, user_id: int) - dict: 获取用户画像 优先从缓存读取缓存未命中再从数据库加载 # 检查熔断器状态 if self._is_circuit_open(): # 熔断期间返回降级数据最近一次成功缓存的快照 degraded_data self._get_degraded_data(user_id) if degraded_data: return degraded_data # 如果连降级数据都没有返回空画像 return {user_id: user_id, profile: {}} # 尝试从缓存获取 cached_profile self._get_from_cache(user_id) if cached_profile: return cached_profile # 缓存未命中从数据库加载 try: profile self._load_from_database(user_id) # 写入缓存设置5分钟过期 self._set_to_cache(user_id, profile, ttl300) # 重置熔断器计数 self._reset_circuit_breaker() return profile except Exception as e: # 记录失败 self._record_failure() # 尝试降级 degraded_data self._get_degraded_data(user_id) if degraded_data: return degraded_data raise e def _get_from_cache(self, user_id: int) - Optional[dict]: 从Redis缓存获取用户画像 cache_key fuser_profile:{user_id} cached self.redis.get(cache_key) if cached: return json.loads(cached) return None def _set_to_cache(self, user_id: int, profile: dict, ttl: int 300): 写入Redis缓存 cache_key fuser_profile:{user_id} self.redis.setex(cache_key, ttl, json.dumps(profile)) def _get_degraded_data(self, user_id: int) - Optional[dict]: 获取降级数据缓存中的历史快照 # 降级数据使用不同的key避免被正常缓存覆盖 cache_key fuser_profile_degraded:{user_id} cached self.redis.get(cache_key) if cached: return json.loads(cached) return None def _is_circuit_open(self) - bool: 检查熔断器是否打开 state self.circuit_breaker_state if not state[is_open]: return False # 检查熔断超时 if state[last_failure_time] and \ (datetime.now() - state[last_failure_time]).seconds self.CIRCUIT_BREAKER_TIMEOUT: # 超时后自动半开 state[is_open] False state[failure_count] 0 return False return True def _record_failure(self): 记录一次失败 state self.circuit_breaker_state state[failure_count] 1 state[last_failure_time] datetime.now() if state[failure_count] self.CIRCUIT_BREAKER_THRESHOLD: state[is_open] True def _reset_circuit_breaker(self): 重置熔断器 self.circuit_breaker_state[failure_count] 0 self.circuit_breaker_state[is_open] False# 使用示例if __name__ __main__: # 初始化Redis客户端 redis_client redis.Redis(hostredis-prod, port6379, decode_responsesTrue) aggregator UserProfileAggregator(redis_client) # 模拟并发请求 import threading def worker(user_id): try: profile aggregator.get_user_profile(user_id) print(fUser {user_id} profile: {profile}) except Exception as e: print(fFailed to get profile for {user_id}: {e}) threads [] for i in range(100): # 100个并发请求 t threading.Thread(targetworker, args(i % 10,)) # 10个不同用户 threads.append(t) t.start() for t in threads: t.join()## 最终结果与反思经过以上优化1.SQL优化通过精确匹配和索引单次查询从15秒降至50ms。2.连接池避免频繁创建连接降低数据库压力。3.多级缓存本地缓存Redis缓存将99%的请求拦截在数据库之外。4.熔断机制当数据库异常时自动降级到缓存数据防止雪崩。优化上线后接口响应时间稳定在10ms以内错误率降至0.01%再也没有出现过凌晨告警。这次事故让我深刻体会到性能优化不是单一维度的改进而是需要从SQL、架构、缓存、容错等多个层面系统性地解决问题。## 总结生产事故是最好的老师。这次经历教会我三个核心原则1.预防胜于治疗上线前一定要做压力测试特别是对数据库查询。2.缓存不是银弹缓存能解决性能问题但必须配合熔断和降级否则缓存雪崩会引发更大的灾难。3.监控驱动优化没有监控你永远不知道问题是SQL慢、连接池不足还是代码逻辑有bug。APM工具和日志分析是定位问题的利器。最后记住一句真理在分布式系统中任何组件都可能失败。你的代码不仅要能处理成功路径更要优雅地处理失败路径。

相关新闻

pywencai终极指南:3分钟搞定同花顺问财数据采集的Python神器

pywencai终极指南:3分钟搞定同花顺问财数据采集的Python神器

pywencai终极指南:3分钟搞定同花顺问财数据采集的Python神器 【免费下载链接】pywencai 获取同花顺问财数据 项目地址: https://gitcode.com/gh_mirrors/py/pywencai 还在为金融数据分析而烦恼吗?每天需要手动查询股票信息、复制粘贴财务数据&…

2026/7/26 18:53:23阅读更多 →
嵌入式DSP视频编码优化:硬件扩展指令集在运动估计与像素插值中的应用

嵌入式DSP视频编码优化:硬件扩展指令集在运动估计与像素插值中的应用

1. 项目概述与核心价值在嵌入式视频处理领域,尤其是实时编码场景下,性能与功耗是永恒的博弈。当你在一个主频有限的DSP上跑H.264或MPEG-4编码器时,最让你头疼的往往是运动估计(Motion Estimation, ME)和离散余弦变换&a…

2026/7/26 18:51:23阅读更多 →
OMAP5910 I2C控制器寄存器详解与驱动开发实战

OMAP5910 I2C控制器寄存器详解与驱动开发实战

1. OMAP5910 I2C控制器:从寄存器到代码的实战指南在嵌入式开发领域,尤其是面对像OMAP5910这类集成了丰富外设的复杂应用处理器时,与外设芯片的通信是基本功。I2C总线以其简洁的两线(SDA, SCL)和灵活的多主…

2026/7/26 18:51:23阅读更多 →
48-程序员场景-技术笔记与代码管理

48-程序员场景-技术笔记与代码管理

48 程序员场景:技术笔记与代码管理 300个代码片段和50个项目的记忆 阿栋是一个全栈开发者,React和Node.js都有三年经验。他最大的烦恼不是写代码,而是——记不住。 “你有没有这种经历?半年前写过一个很优雅的递归函数,现在要用的时候却想不起来怎么写。或者在Stack Ov…

2026/7/27 0:54:35阅读更多 →
46-职场场景-项目管理与知识沉淀

46-职场场景-项目管理与知识沉淀

46 职场场景:项目管理与知识沉淀 三个项目,一个看板 王姐是某互联网公司的技术团队负责人,手下管理着三个并行项目:一个核心产品的版本迭代、一个技术债务清理专项、还有一个跨部门合作的创新项目。听起来就已经够忙了,但她还有一个特殊的"秘密武器"。 “以前…

2026/7/27 0:54:35阅读更多 →
ComfyUI IPAdapter Plus完整指南:3步掌握AI图像风格迁移技术

ComfyUI IPAdapter Plus完整指南:3步掌握AI图像风格迁移技术

ComfyUI IPAdapter Plus完整指南:3步掌握AI图像风格迁移技术 【免费下载链接】ComfyUI_IPAdapter_plus 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI_IPAdapter_plus 你是否想要在AI图像生成中实现精准的风格控制和人物特征保留?ComfyU…

2026/7/27 0:54:35阅读更多 →
新手救星|不用死记硬背,C语言从零到通透竟这么简单

新手救星|不用死记硬背,C语言从零到通透竟这么简单

刚踏入 计算机专业的大一新生 ,或是 想入门C语言的新手们 ,是不是都有过这样的崩溃时刻? 翻开一本C语言书,上来就是晦涩的语法、难懂的术语, #include到底是啥 ?stdio.h藏着什么秘密?指针更是像…

2026/7/27 0:54:35阅读更多 →
WaveTools鸣潮工具箱终极指南:从画质优化到抽卡分析的一站式解决方案

WaveTools鸣潮工具箱终极指南:从画质优化到抽卡分析的一站式解决方案

WaveTools鸣潮工具箱终极指南:从画质优化到抽卡分析的一站式解决方案 【免费下载链接】WaveTools 🧰鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 你是否正在寻找一款能够提升《鸣潮》游戏体验的全面工具?WaveT…

2026/7/27 0:54:35阅读更多 →
终极指南:3分钟免费实现GitHub界面全面汉化

终极指南:3分钟免费实现GitHub界面全面汉化

终极指南:3分钟免费实现GitHub界面全面汉化 【免费下载链接】github-chinese GitHub 汉化插件,GitHub 中文化界面。 (GitHub Translation To Chinese) 项目地址: https://gitcode.com/gh_mirrors/gi/github-chinese 还在为GitHub的英文界面而头疼…

2026/7/27 0:52:35阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/26 0:01:28阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/26 0:01:28阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/26 0:01:28阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:24阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:24阅读更多 →
2007-2023年各市区县生态文明建设示范区DID

2007-2023年各市区县生态文明建设示范区DID

数据简介 自改革开放以来,我国依赖高投入、高资源消耗和高污染等传统发展模式实现了经济短期内的快速增长, 然而这也导致了严重的生态环境危机。因此,国家有力于推动企业高质量经济发展,协同生态保护的方针,从而从201…

2026/7/27 0:00:24阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/25 23:03:25阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/26 19:05:21阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/26 19:05:21阅读更多 →