个人应用服务最近都集中部署单台服务器以减少日常开销,所以会长时间保持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
)、StartServers
、MinSpareServers
、MaxSpareServers
的值。
- 修改
- Nginx:内存占用通常很低,主要优化PHP进程。
- Apache:主要优化进程数和每个进程的内存占用。
-
如果是 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
),尝试将其降低。
- 检查其配置文件,通常都有设置内存限制的参数(例如JVM的
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
总结与行动清单
- 正确心态:明白
已用
内存高是Linux正常行为,关注可用(available)
。 - 立即行动:运行
sudo sync; echo 3 > /proc/sys/vm/drop_caches
快速释放缓存,观察效果。 - 诊断病因:运行
htop
或ps aux --sort=-%mem | head -10
,找出前3名内存消耗进程。 - 对症下药:
- 如果是MySQL:调低
innodb_buffer_pool_size
。 - 如果是PHP-FPM:调低
pm.max_children
。 - 如果是Apache:调低
MaxRequestWorkers
等参数。
- 如果是MySQL:调低
- 添加保险:使用上述命令添加一个2GB的Swap文件,这是防止应用崩溃的最简单有效的手段。
- 长期监控:养成习惯,定期使用
htop
查看系统状态。
按照这个流程走一遍,你的服务器内存压力应该能得到显著缓解。这些优化手段在生产环境中非常常见,请放心操作。
问题二:swapon 我已经创建,是否可以暂时先不用再处理内存占用的问题
这是一个非常好的问题,也是很多Linux管理员会有的想法。创建Swap空间确实是一个重要的安全网,但让我们来详细分析一下当前的情况,以帮助你做出最佳决策。
核心结论:可以,但必须有后续动作。
创建了Swap,相当于给你的服务器买了一份“保险”。它极大地降低了因为内存耗尽而导致服务崩溃、进程被系统强制杀死的风险。从这个角度来说,你的服务器暂时安全了,你可以不用立刻、手忙脚乱地去处理内存问题。
但是,这绝对不意味着可以高枕无忧,不用再处理内存问题了。 原因如下:
- 性能惩罚严重:Swap的本质是拿硬盘空间来模拟内存。硬盘(即使是SSD)的读写速度远远低于真正的内存(DDR4内存比SSD快几十甚至上百倍)。当系统开始使用Swap时(称为“换页”),应用程序的响应速度会显著变慢。如果你的用户访问网站时感觉卡顿,体验会非常差。
- 磁盘I/O压力:频繁的换页操作会大量读写硬盘,这会占用宝贵的磁盘I/O资源。如果你的服务器上还有数据库或其他需要频繁读写磁盘的应用,它们也会被拖慢,导致整个系统性能下降。
- 掩盖了真正的问题:Swap的存在让内存不足的问题不再“致命”,但它没有解决“为什么内存会不足”这个根本问题。可能是一个配置错误,或者某个进程存在内存泄漏(内存占用随时间不断增长,永不释放),Swap只是暂时掩盖了这些隐患。
给你的行动建议:一个分阶段的策略
既然已经创建了Swap,你的压力就小了很多。我建议你采取以下步骤:
第一阶段:监控与观察(现在就开始)
现在有了Swap护航,你可以更从容地观察系统,收集数据,找出根源。
-
观察Swap的使用情况:
free -h # 或者更直观地 watch -n 5 'free -h'
关注
Swap
行下的used
列。如果这个数字一直在增长,甚至占用了很大一部分,说明物理内存真的不够用了,系统正在频繁依赖Swap,性能已经受到了影响。 -
使用综合工具监控:
htop
在
htop
界面中,你可以同时看到:- 哪些进程占用了最多的内存和CPU。
- 内存条和Swap条的颜色变化。当Swap被使用时,它的颜色会发生变化,非常直观。
-
使用
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
中的 si
和 so
几乎始终为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
,观察 Swap
的 used
值是否下降,Available
物理内存是否上升。
第 3 步:禁用 Swap 文件
现在,你可以安全地关闭 Swap 文件了。这个操作会立即将 Swap 中的数据写回物理内存(只要物理内存足够)。
sudo swapoff -v /swapfile
-v
参数表示详细模式,会让你看到操作进度。- 请注意: 如果你的 Swap 使用量很大(例如好几个GB),这个操作可能会花费几十秒到几分钟,期间系统会变得非常繁忙(I/O 等待很高),这是正常现象。耐心等待命令完成,切勿中途中断。
第 4 步:验证 Swap 已禁用
操作完成后,再次检查确认 Swap 已被成功关闭。
free -h
swapon --show
free -h
的输出中,Swap
行的total
和used
应该都变为0
。swapon --show
应该没有任何输出,表示系统已无激活的 Swap 空间。
第 5 步:从 /etc/fstab
中移除启动项
这是非常关键的一步,防止下次重启后系统又自动挂载这个 Swap 文件。
使用文本编辑器(如 nano
或 vim
)打开 /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
总结与最终检查清单
- 检查:
free -h
和vmstat
确认系统状态。 - 释放缓存:(可选)
sudo sync; echo 3 > /proc/sys/vm/drop_caches
- 禁用 Swap:
sudo swapoff -v /swapfile
(耐心等待完成) - 验证:再次运行
free -h
和swapon --show
确认已禁用。 - 清理配置:编辑
/etc/fstab
,删除或注释掉 Swap 相关行。 - 删除文件:
sudo rm /swapfile
完成以上所有步骤后,你的 Swap 文件就被安全且彻底地删除了。之后请继续关注系统的内存使用情况(htop
),确保之前进行的内存优化(调整 MySQL、PHP 等配置)是有效的,物理内存足以支撑你的应用正常运行。
我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~ 😃
转发请注明参考文章地址,非常感谢!!!
Q.E.D.