如何优化linux服务器过高的内存占用?

2025-09-11   


个人应用服务最近都集中部署单台服务器以减少日常开销,所以会长时间保持90%以上的内存占用,向AI学习一下如何优化linux服务器过高的内存占用问题。

问题一:如何优化linux服务器过高的内存占用

你好,完全理解你的处境。在预算有限的情况下,对现有服务器进行优化是运维的必备技能。别担心,从你提供的数据来看,情况并没有看起来那么糟糕。

核心结论:你的内存其实够用!

首先,我们来正确解读你的内存使用情况,这是最关键的一步,能让你安心:

在Linux系统中,内存管理的原则是:不用白不用。它会利用尽可能多的内存来作为磁盘缓存(cache)和缓冲区(buffer),以加速系统的读写速度。当应用程序需要更多内存时,系统会自动释放这部分缓存。

  • 总内存: 3719 MB (~3.7GB)
  • 已用: 3374 MB — 这个数字包含了被用作缓存和缓冲区的内存,所以它看起来很高,但并不可怕。
  • 可用(available): 112 MB — 这是关键指标!这个值指的是当前真正可供应用程序使用的内存。它确实偏低了,说明系统正在充分利用内存,但还没到危险的地步。
  • buff/cache: 230 MB — 这就是被用作缓存的内存,可以被快速释放。

所以,你的服务器目前处于内存使用紧张但尚未耗尽的状态。优化目标是释放一些缓存,并找出哪些进程占用了过多内存,从而有针对性地进行配置调整。


优化方案(无需花钱)

1. 立即释放缓存(临时缓解)

这是一个安全操作,内核会在需要时自动处理,但手动操作可以立即获得可用内存。

# 释放 pagecache, dentries and inodes
sync; echo 3 > /proc/sys/vm/drop_caches

说明

  • sync:将系统缓冲区数据同步到磁盘,确保数据安全。
  • echo 1 > ...:只释放页缓存。
  • echo 2 > ...:只释放目录项和inode缓存。
  • echo 3 > ...:释放上述所有缓存。
    执行后,你的 可用(available) 内存会立刻增加(buff/cache 会减少)。这是一个临时措施,缓存之后还会慢慢增加。可以在感觉应用变慢时执行。

2. 诊断分析:找出内存消耗大户

优化必须有的放矢。请使用以下命令找出真正的“元凶”。

a. 综合监控

htop

或者用经典的 top,然后按 Shift+M 按内存使用排序。查看排在前三的进程是哪些。

b. 精确查看每个进程的内存

ps aux --sort=-%mem | head -10

这个命令会列出内存使用率最高的前10个进程。

c. 更详细的内存分析工具

sudo apt install smem # 如果系统是Debian/Ubuntu
sudo yum install smem # 如果系统是CentOS/RHEL
smem -s rss -r | head -10

smem 工具能更准确地报告物理内存占用(RSS、PSS)。

3. 针对性优化(根据诊断结果)

根据第2步的发现,进行以下针对性优化:

  • 如果是 MySQL/MariaDB

    • 检查 /etc/my.cnf/etc/mysql/my.cnf 中的配置。
    • 关键参数:innodb_buffer_pool_size(通常是最大内存占用项)。如果你的数据库不大,可以将其调小。例如从1G调整为512M甚至256M。
    • 其他参数:key_buffer_size, query_cache_size (MariaDB 10.3.9+中已弃用),都可以适当调小。
    • 建议:可以先尝试将 innodb_buffer_pool_size 设置为总内存的 1/4 到 1/3(例如 800M - 1.2G)。
  • 如果是 Apache/Nginx

    • Apache:主要优化进程数和每个进程的内存占用。
      • 修改 /etc/apache2/mods-available/mpm_prefork.conf(如果使用prefork模式)。
      • 降低 MaxRequestWorkers(或旧版本的MaxClients)、StartServersMinSpareServersMaxSpareServers 的值。
    • Nginx:内存占用通常很低,主要优化PHP进程。
  • 如果是 PHP-FPM(非常常见):

    • 修改 /etc/php/7.x/fpm/pool.d/www.conf(版本号可能不同)。
    • 关键参数:
      • pm.max_children:最大子进程数。每个进程会占用一定内存,总数乘以每个进程的内存就是总消耗。这是最有效的调优参数
      • pm.start_servers:启动时的进程数。
      • pm.min_spare_servers / pm.max_spare_servers:空闲进程数范围。
    • 如何计算:假设你的PHP进程平均占用30MB内存,你有1GB内存可供PHP使用(需为系统和其他进程留出空间),那么 max_children 可以设置为 1000MB / 30MB ≈ 33。建议保守设置为25-28,留出余量。
  • 如果是其他特定应用(如Node.js, Java, Python应用):

    • 检查其配置文件,通常都有设置内存限制的参数(例如JVM的 -Xmx),尝试将其降低。

4. 启用 Swap 空间(应急救生艇)

Swap是硬盘上的一块空间,当物理内存不足时,系统可以将不常用的内存页换到Swap中。它会影响性能(因为硬盘比内存慢得多),但可以防止程序因内存不足而崩溃。

检查当前是否有Swap

swapon --show
free -h

如果没有或者很小,可以添加一个Swap文件

# 1. 创建一个2GB的文件(大小自定,通常是物理内存的0.5到1倍)
sudo fallocate -l 2G /swapfile
# 2. 设置正确的权限
sudo chmod 600 /swapfile
# 3. 格式化为swap
sudo mkswap /swapfile
# 4. 启用它
sudo swapon /swapfile
# 5. 让它开机自动挂载
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 6. 调整 swappiness(可选),这个值(0-100)表示系统使用swap的积极性。越低越倾向于使用物理内存。
# 临时设置
sudo sysctl vm.swappiness=10
# 永久设置
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

总结与行动清单

  1. 正确心态:明白 已用 内存高是Linux正常行为,关注 可用(available)
  2. 立即行动:运行 sudo sync; echo 3 > /proc/sys/vm/drop_caches 快速释放缓存,观察效果。
  3. 诊断病因:运行 htopps aux --sort=-%mem | head -10,找出前3名内存消耗进程。
  4. 对症下药
    • 如果是MySQL:调低 innodb_buffer_pool_size
    • 如果是PHP-FPM:调低 pm.max_children
    • 如果是Apache:调低 MaxRequestWorkers 等参数。
  5. 添加保险:使用上述命令添加一个2GB的Swap文件,这是防止应用崩溃的最简单有效的手段。
  6. 长期监控:养成习惯,定期使用 htop 查看系统状态。

按照这个流程走一遍,你的服务器内存压力应该能得到显著缓解。这些优化手段在生产环境中非常常见,请放心操作。

问题二:swapon 我已经创建,是否可以暂时先不用再处理内存占用的问题

这是一个非常好的问题,也是很多Linux管理员会有的想法。创建Swap空间确实是一个重要的安全网,但让我们来详细分析一下当前的情况,以帮助你做出最佳决策。

核心结论:可以,但必须有后续动作。

创建了Swap,相当于给你的服务器买了一份“保险”。它极大地降低了因为内存耗尽而导致服务崩溃、进程被系统强制杀死的风险。从这个角度来说,你的服务器暂时安全了,你可以不用立刻、手忙脚乱地去处理内存问题。

但是,这绝对不意味着可以高枕无忧,不用再处理内存问题了。 原因如下:

  1. 性能惩罚严重:Swap的本质是拿硬盘空间来模拟内存。硬盘(即使是SSD)的读写速度远远低于真正的内存(DDR4内存比SSD快几十甚至上百倍)。当系统开始使用Swap时(称为“换页”),应用程序的响应速度会显著变慢。如果你的用户访问网站时感觉卡顿,体验会非常差。
  2. 磁盘I/O压力:频繁的换页操作会大量读写硬盘,这会占用宝贵的磁盘I/O资源。如果你的服务器上还有数据库或其他需要频繁读写磁盘的应用,它们也会被拖慢,导致整个系统性能下降。
  3. 掩盖了真正的问题:Swap的存在让内存不足的问题不再“致命”,但它没有解决“为什么内存会不足”这个根本问题。可能是一个配置错误,或者某个进程存在内存泄漏(内存占用随时间不断增长,永不释放),Swap只是暂时掩盖了这些隐患。

给你的行动建议:一个分阶段的策略

既然已经创建了Swap,你的压力就小了很多。我建议你采取以下步骤:

第一阶段:监控与观察(现在就开始)

现在有了Swap护航,你可以更从容地观察系统,收集数据,找出根源。

  1. 观察Swap的使用情况

    free -h
    # 或者更直观地
    watch -n 5 'free -h'
    

    关注 Swap 行下的 used 列。如果这个数字一直在增长,甚至占用了很大一部分,说明物理内存真的不够用了,系统正在频繁依赖Swap,性能已经受到了影响。

  2. 使用综合工具监控

    htop
    

    htop 界面中,你可以同时看到:

    • 哪些进程占用了最多的内存和CPU。
    • 内存条和Swap条的颜色变化。当Swap被使用时,它的颜色会发生变化,非常直观。
  3. 使用 vmstat 检查换页情况

    vmstat 5
    

    重点关注 si (swap in) 和 so (swap out) 这两列。如果它们的值持续大于0,就意味着系统正在不断地在内存和硬盘之间交换数据,这是性能瓶颈的明确信号。

第二阶段:根据监控结果进行根本性优化(在未来几天/一周内完成)

通过第一阶段的监控,你肯定已经找到了内存消耗大户(很可能是MySQL、PHP-FPM或Nginx/Apache)。接下来就按照我们上次讨论的方法进行针对性优化:

  • 调低 MySQL 的 innodb_buffer_pool_size
  • 调低 PHP-FPM 的 pm.max_children
  • 检查是否有内存泄漏:观察某个进程的内存占用是否随时间无限增长。如果是,可能需要重启该服务或检查程序代码。

最终目标

优化的最终目标是:在保证应用稳定运行的前提下,让 vmstat 中的 siso 几乎始终为0,并且Swap的 used 值长期保持不变或只有极少量使用

这意味着你的物理内存已经足够应付日常业务,系统不再需要频繁访问慢速的硬盘来模拟内存,服务器运行在最佳性能状态。

总结

可以暂时不紧张,但绝不能永远不处理。

你把Swap比作汽车的安全气囊好了。发生碰撞时(内存耗尽),它能救你的命(防止系统崩溃),但你绝对不会想天天看到它弹出来。每次它弹出来,都意味着你的车发生了事故(性能受损)。

所以,创建Swap是正确的急救措施,它给了你宝贵的调查和修复时间。请利用好这段时间,找出病根并解决它,而不是永远依赖这个“轮椅”

问题三:如何安全删除 swapon

好的,安全地删除 Swap 文件是一个简单的过程,但必须按照步骤谨慎操作,以确保不会对系统运行中的服务造成影响。

核心原则: 首先确保你的系统当前有足够多的可用物理内存(Available Memory),能够承接目前正在使用 Swap 的那部分数据。如果强行删除正在使用的 Swap,可能会导致系统因瞬间内存不足而崩溃。


安全删除 Swap 的步骤

请严格按照以下顺序操作:

第 1 步:检查当前 Swap 使用情况

首先,你需要确认系统当前是否正在使用 Swap。如果 Swap 使用量为 0,那么可以安全地立即禁用。如果正在使用,则需要先将其中的数据转移回物理内存。

free -h

查看输出中 Swap 那一行的 used 列。如果 used 的值不是 0(例如 2.1G),说明有数据正在 Swap 中。
同时,使用 vmstat 检查系统换页活动:

vmstat 2 5
  • 如果 si (swap in) 和 so (swap out) 两列的值大部分时间都是 0,说明系统当前没有频繁地使用 Swap,此时操作更安全。
  • 如果 si 有数值,说明系统正在从 Swap 读数据到内存,这是你可以操作的时机。
  • 如果 so 有数值,说明系统正在被迫将内存数据换出到 Swap,这意味着物理内存不足!此时绝对不能禁用 Swap!

第 2 步(可选但推荐):释放系统缓存

这是一个很好的做法,可以手动释放一些缓存页,为物理内存腾出更多空间,以便系统能更容易地将 Swap 中的数据转移回来。

sudo sync; echo 3 > /proc/sys/vm/drop_caches

再次运行 free -h,观察 Swapused 值是否下降,Available 物理内存是否上升。

第 3 步:禁用 Swap 文件

现在,你可以安全地关闭 Swap 文件了。这个操作会立即将 Swap 中的数据写回物理内存(只要物理内存足够)。

sudo swapoff -v /swapfile
  • -v 参数表示详细模式,会让你看到操作进度。
  • 请注意: 如果你的 Swap 使用量很大(例如好几个GB),这个操作可能会花费几十秒到几分钟,期间系统会变得非常繁忙(I/O 等待很高),这是正常现象。耐心等待命令完成,切勿中途中断

第 4 步:验证 Swap 已禁用

操作完成后,再次检查确认 Swap 已被成功关闭。

free -h
swapon --show
  • free -h 的输出中,Swap 行的 totalused 应该都变为 0
  • swapon --show 应该没有任何输出,表示系统已无激活的 Swap 空间。

第 5 步:从 /etc/fstab 中移除启动项

这是非常关键的一步,防止下次重启后系统又自动挂载这个 Swap 文件。
使用文本编辑器(如 nanovim)打开 /etc/fstab 文件:

sudo nano /etc/fstab

找到添加 Swap 文件时写入了那一行,它通常长这样:

/swapfile none swap sw 0 0

将这一行直接删除,或者在其行首添加一个 # 符号将其注释掉:

# /swapfile none swap sw 0 0

保存并退出编辑器(在 nano 中是 Ctrl+X,然后按 Y 确认,再按回车)。

第 6 步(最终步骤):删除 Swap 文件

既然已经确保系统不再使用它,你就可以安全地删除这个文件来释放磁盘空间了。

sudo rm /swapfile

总结与最终检查清单

  1. 检查free -hvmstat 确认系统状态。
  2. 释放缓存:(可选)sudo sync; echo 3 > /proc/sys/vm/drop_caches
  3. 禁用 Swapsudo swapoff -v /swapfile (耐心等待完成)
  4. 验证:再次运行 free -hswapon --show 确认已禁用。
  5. 清理配置:编辑 /etc/fstab,删除或注释掉 Swap 相关行。
  6. 删除文件sudo rm /swapfile

完成以上所有步骤后,你的 Swap 文件就被安全且彻底地删除了。之后请继续关注系统的内存使用情况(htop),确保之前进行的内存优化(调整 MySQL、PHP 等配置)是有效的,物理内存足以支撑你的应用正常运行。

我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~ 😃
转发请注明参考文章地址,非常感谢!!!

Q.E.D.


Hi!欢迎访问 fx67ll.com 的个人博客站点!Code is my life ~