服务器内存不够用怎么办?SWAP配置与内存泄漏排查实战
服务器内存不够用了怎么解决?SWAP 配置与内存泄漏排查实战
服务器内存不足时,Linux 内核会启动 OOM Killer(Out-of-Memory Killer) 机制,强制杀掉内存占用最大的进程——很多时候,被杀的恰好是你的 MySQL、Nginx 或核心应用。本文从现象判断到根因处理,提供一套完整的内存问题解决方案。
一、快速判断:内存是否真的不足?
free -h典型输出解读:
total used free shared buff/cache available
Mem: 3.8Gi 2.9Gi 156Mi 45Mi 743Mi 651Mi
Swap: 1.0Gi 891Mi 133Mi关键指标说明:
available(651Mi):真正可供应用使用的内存,这个值才是判断内存是否紧张的关键,而不是freebuff/cache(743Mi):Linux 用于文件缓存的内存,在应用需要时可被回收,不代表内存浪费Swap used(891Mi):SWAP 使用率高说明物理内存已经不够用,系统正在用磁盘补充内存,性能会显著下降
判断标准:available 持续低于总内存的 10%,或 SWAP 使用率持续超过 50%,说明内存确实不足,需要处理。
二、查看 OOM Killer 是否已经杀过进程
# 检查内核日志中的 OOM 记录
sudo dmesg | grep -i "oom\|killed"
# 或查看系统日志
sudo grep -i "out of memory\|oom_kill" /var/log/syslog | tail -20如果看到类似以下输出,说明 OOM Killer 已经工作过:
kernel: Out of memory: Kill process 1234 (mysql) score 892 or sacrifice child
kernel: Killed process 1234 (mysql) total-vm:1048576kB, anon-rss:524288kB三、定位内存使用最多的进程
# 按内存使用量降序排列进程(%MEM 列)
ps aux --sort=-%mem | head -15
# 或在 top 中按 M 键按内存排序
top # 进入后按 M常见内存消耗大户:
- MySQL / MariaDB:
innodb_buffer_pool_size设置过大 - PHP-FPM:进程数过多,每个进程约占 30~80MB
- Redis:未设置 maxmemory 导致无限增长
- Node.js 应用:内存泄漏最常见的运行时之一
- Java 应用:JVM 堆内存配置过大或泄漏
四、临时方案:配置 SWAP 虚拟内存
SWAP 是在磁盘上划出一块空间模拟内存,当物理内存不足时系统可以将不活跃的内存页交换到 SWAP,避免 OOM Killer 杀进程。
⚠️ 重要说明:SWAP 的读写速度远低于物理内存(磁盘 vs 内存),频繁使用 SWAP 会导致系统明显变慢。SWAP 是应急缓冲,不能替代充足的物理内存。
Step 1:创建 SWAP 文件
# 创建 2GB 的 SWAP 文件(推荐大小为物理内存的 1~2 倍,最大 8GB)
sudo fallocate -l 2G /swapfile
# 设置正确的权限(SWAP 文件不应被其他用户读取)
sudo chmod 600 /swapfile
# 将文件格式化为 SWAP 格式
sudo mkswap /swapfileStep 2:启用 SWAP
# 立即启用 SWAP(重启后失效)
sudo swapon /swapfile
# 验证 SWAP 是否生效
free -h # Swap 行应显示 2GB 总量Step 3:设置开机自动挂载
# 写入 /etc/fstab,开机自动挂载
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabStep 4:调整 swappiness(SWAP 使用倾向)
# 查看当前 swappiness 值(默认60)
cat /proc/sys/vm/swappiness
# 设置为 10(更倾向于使用物理内存,减少不必要的 SWAP 使用)
sudo sysctl vm.swappiness=10
# 永久生效
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.confswappiness 取值 0~100:值越小,系统越倾向于保留物理内存不换出;服务器环境通常建议设置为 10~20。
五、减少各服务内存占用的实用配置
MySQL:限制 InnoDB 缓冲池
# /etc/mysql/mysql.conf.d/mysqld.cnf
# 将 buffer pool 设置为可用内存的 50~60%(而非默认的更大值)
innodb_buffer_pool_size = 512M # 1GB 内存机器建议设 400~512M
# 限制最大连接数(每个连接约占 1~8MB)
max_connections = 50PHP-FPM:减少进程数
# /etc/php/8.2/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 10 # 内存有限时降低最大进程数
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_requests = 200 # 每个进程处理200次请求后重启,防止内存泄漏积累Redis:设置最大内存限制
# /etc/redis/redis.conf
maxmemory 256mb # 限制最大使用 256MB
maxmemory-policy allkeys-lru # 内存满时淘汰最久未使用的 keyNginx:限制 worker 进程内存
# /etc/nginx/nginx.conf
# worker 进程数设置为 CPU 核心数(而非 auto,内存紧张时不宜过多)
worker_processes 2;
# 每个连接的读写缓冲区减小
client_body_buffer_size 10K;
client_header_buffer_size 1k;
large_client_header_buffers 2 1k;六、内存泄漏排查:进程内存持续增长怎么办?
内存泄漏的特征是:某个进程的内存占用随时间持续增长,即使业务量没有增加。
监控进程内存随时间的变化
# 每隔5秒打印进程 1234 的内存使用(VmRSS = 实际物理内存)
while true; do
echo "$(date): $(grep VmRSS /proc/1234/status)"
sleep 5
doneNode.js 内存泄漏排查
# 启动时开启内存分析
node --expose-gc --inspect app.js
# 或者定期打印内存使用
setInterval(() => {
const used = process.memoryUsage();
console.log(`RSS: ${Math.round(used.rss/1024/1024)}MB, Heap: ${Math.round(used.heapUsed/1024/1024)}MB`);
}, 30000);如果 heapUsed 持续增长而不下降,说明存在内存泄漏。常见原因:事件监听器未移除、全局缓存无上限增长、闭包引用阻止 GC 回收。
防止内存泄漏的应急方案:定时重启
如果无法立即定位泄漏根因,可以临时配置定时重启应用进程(凌晨低峰时段),以释放积累的内存:
# 每天凌晨4点重启 Node 应用(通过 PM2)
0 4 * * * pm2 restart app_name这是治标不治本的应急措施,需要同步排查根因。
七、预防为主:内存使用监控告警
sudo nano /usr/local/bin/memory_alert.sh#!/bin/bash
THRESHOLD=90 # 内存使用率告警阈值(90%)
# 计算内存使用率
TOTAL=$(grep MemTotal /proc/meminfo | awk '{print $2}')
AVAILABLE=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
USED_PCT=$(( (TOTAL - AVAILABLE) * 100 / TOTAL ))
if [ "$USED_PCT" -gt "$THRESHOLD" ]; then
echo "⚠️ 内存告警:$(hostname) 内存使用率已达 ${USED_PCT}%(可用:$((AVAILABLE/1024))MB)" \
| mail -s "内存空间告警" your@email.com
fisudo chmod +x /usr/local/bin/memory_alert.sh
# 每15分钟检查一次
(crontab -l; echo "*/15 * * * * /usr/local/bin/memory_alert.sh") | crontab -总结
Linux 服务器内存不足的解决思路按优先级排列:
- 🔍 确认根因:用
free -h和ps aux定位内存消耗大户 - ⚙️ 优化配置:减小 MySQL buffer pool、PHP-FPM 进程数、Redis maxmemory
- 💾 配置 SWAP:作为应急缓冲,防止 OOM Killer 突然杀进程
- 🔬 排查泄漏:监控进程内存随时间的变化,定位并修复内存泄漏
- 📈 升级配置:如果优化后仍不够,考虑升级服务器内存规格
后浪云香港云服务器支持在线升配内存,无需重装系统和迁移数据,在控制台操作即可完成,欢迎按业务需求灵活调整配置。
版权声明:
作者:后浪云
链接:https://idc.net/help/442643/
文章版权归作者所有,未经允许请勿转载。
THE END
