|
|
这里或许是互联网从业者的最后一片净土,随客社区期待您的加入!
您需要 登录 才可以下载或查看,没有账号?立即注册
×
在服务器运维、应用部署或系统性能优化过程中,我们经常会听到一个概念——僵尸内存(Zombie Memory)。虽然“僵尸进程”这个词比较常见,但“僵尸内存”却经常让人误以为是 Linux 系统的一种结构。实际上,僵尸内存并不是 Linux 的正式概念,而是运维人员为了描述异常占用却无法释放的内存而使用的俗称。
本文将带你理解什么是僵尸内存、为什么会出现、如何诊断以及如何修复。
一、僵尸内存的定义
僵尸内存(Zombie Memory)指的是:
被应用程序占用,但由于程序 Bug 或系统异常,已经无法正常释放的内存。即使进程已结束或不再使用这些内存,它们仍被系统标记为“已使用”,无法再次分配。
这种状态会导致:
- 可用内存越来越少
- 系统变慢甚至 OOM(Out Of Memory)
- 某些程序频繁被系统杀死(例如 mysqld、java 等占内存应用)
二、僵尸内存的常见表现
出现僵尸内存时,你可能看到如下现象:
1. free -m 显示“已用内存”不断增加,但没有对应进程在占用
看到:
- used 一直涨
- buff/cache 没什么变化
- 但 top、htop 又找不到占内存的进程
2. OOM Killer 频繁触发
在 /var/log/messages 或 dmesg 中看到:
Out of memory: Kill process xxx (mysqld) score 987 3. 程序明明已经退出,但占用的内存仍未释放
例如 java 崩溃后仍占用大量内存块。
三、导致僵尸内存的根本原因
僵尸内存通常由以下问题引起:
1. 程序内存泄漏(Memory Leak)
最常见原因。
某些程序申请了内存但没有正确释放,导致:
- 该进程占用的内存持续增长
- 内存碎片化
- 内存在进程退出后仍没有正常释放
常发生在:
- C/C++ 程序
- 自定义模块
- 第三方插件
- 长期运行的守护进程(Nginx 模块、PHP-FPM、老版本 Java 应用等)
2. Kernel 内存泄漏(通常来自驱动或内核模块)
典型特征:
- top 查不到占用大量内存的进程
- slab 占用巨大
查看 slab:
常见触发源:
- 错误的网卡驱动
- 文件系统 Bug
- Docker overlayfs 泄漏
- 高速网络 + 某些内核版本的内存管理 Bug
- 长时间运行未重启的系统
3. 文件被进程删除但仍占用内存(tmpfs / pagecache)
例如:
- 日志文件过大
- 程序执行时删除了文件句柄
- 内存中的文件句柄仍被占用
查看:
如果看到大量:
- /var/log/app.log (deleted)
复制代码 说明该文件本体删了,但程序仍在占着内存。
4. Docker、K8s 容器造成的内存异常
容器系统中的常见问题:
- 容器内内存泄漏
- overlay2 缓存泄漏
- 容器退出后 Cgroup 未释放资源
查看:
5. 大量 Page Cache 未及时回收
当执行大量文件 I/O 后,系统会缓存文件内容。
如果未及时回收,看起来像内存被“吃掉”。
四、如何诊断僵尸内存?(重点)
1. 查进程内存占用
- ps aux --sort=-rss | head
复制代码 2. 查看 Slab 内存是否异常
- grep -i slab /proc/meminfo
复制代码 如果 slab 很大(例如几十GB),通常是内核泄漏。
3. 查找被删除但仍占用的文件
4. 检查 docker/kubernetes 内存占用
- cat /sys/fs/cgroup/memory/memory.usage_in_bytes
复制代码 5. 检查 pagecache
- cat /proc/meminfo | grep -i cache
复制代码 五、如何修复僵尸内存?
1. 重启对应服务
例如:
systemctl restart php-fpm
systemctl restart nginx
systemctl restart docker 通常能释放进程泄漏的内存。
2. 清理 pagecache(安全)
- sync; echo 3 > /proc/sys/vm/drop_caches
复制代码 3. 重启 Docker 或 K8s 节点
处理容器造成的内存泄漏:
4. 更新内核或驱动
如果 slab 异常巨大,多半是内核泄漏。
升级内核通常可以解决。
5. 对应用进行内存泄漏排查
使用:
- valgrind
- pmap
- strace
- heapdump(JAVA)
- php-fpm slowlog
6. 最后手段:重启系统
当内核级别的泄漏导致内存无法回收时,只能通过系统重启解决。
六、如何预防僵尸内存?
- 使用稳定版本的内核与驱动
- 定期重启高风险程序(守护进程)
- 有限制地使用第三方模块
- 对 C/C++ 程序做 valgrind 测试
- 监控内存增长趋势(Prometheus + Grafana)
- 配置 OOM 保护策略
总结
僵尸内存不是操作系统正式术语,而是指:
由于程序或系统漏洞导致无法被正常释放的内存,逐渐侵蚀系统可用资源,使系统变得缓慢甚至崩溃。
它可能来自:
- 应用内存泄漏
- 内核泄漏
- 文件句柄未释放
- Docker/K8s 问题
- PageCache 堆积
通过系统监控、日志分析以及对特定模块排查,可以有效避免僵尸内存问题,保持系统稳定运行。
|
|