一次Python内存泄漏的真实排查经历
上周线上服务内存占用一路飙升,从200MB涨到2GB,最后OOM被系统杀了。排查过程挺曲折的,分享一下,希望帮到踩类似坑的朋友。 现象 监控告警,服务内存持续增长,重启后从200MB开始,几小时后又到2GB。典型的内存泄漏特征。 排查过程 第一步:确认是不是真的泄漏 先用tracemalloc追踪内
上周线上服务内存占用一路飙升,从200MB涨到2GB,最后OOM被系统杀了。排查过程挺曲折的,分享一下,希望帮到踩类似坑的朋友。

现象
监控告警,服务内存持续增长,重启后从200MB开始,几小时后又到2GB。典型的内存泄漏特征。
排查过程
第一步:确认是不是真的泄漏
先用tracemalloc追踪内存分配:
import tracemalloc
tracemalloc.start()# ... 运行业务代码 ...snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
for stat in top_stats[:10]:
print(stat)
输出显示某个字典对象一直在增长,占用从几MB涨到了几百MB。
第二步:定位问题代码
追了一下,发现是一个全局缓存字典没有淘汰机制:
# 问题代码:缓存只进不出
_user_cache = {}def get_user(user_id):
if user_id not in _user_cache:
_user_cache[user_id] = fetch_user_from_db(user_id)
return _user_cache[user_id]
看起来没问题对吧?但我们的场景是用户量很大,每个用户第一次访问就缓存了,之后永远不会清理。随着用户访问越来越多,缓存就越积越大。
第三步:修复
最简单的方案,换成LRU缓存:
from functools import lru_cache@lru_cache(maxsize=10000)
def get_user(user_id):
return fetch_user_from_db(user_id)
加了maxsize后,缓存超过10000条就自动淘汰最久没访问的。内存占用稳定在300MB左右,问题解决。
反思
其实这个坑很低级,但当时写代码的时候确实没想到用户量会到这个级别。几个教训:
- 全局缓存一定要有淘汰策略,不管你用
lru_cache、cachetools.TTLCache还是Redis,总之不能只进不出 - 上线前做一下内存压测,模拟一段时间的持续请求,看内存是否持续增长
tracemalloc是排查Python内存问题的利器,比凭直觉猜靠谱多了
顺便说一句,如果缓存的数据来自API调用,还要考虑缓存过期的问题。之前我有个项目调大模型API,结果缓存了过期的响应,debug了好久才反应过来。国内用这些API有时候响应慢或者不稳定,我后来换了个中转站,响应速度好了不少,缓存命中率也提上去了。
就这些,希望对你有帮助。Python
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















