导读:年付几美元的小鸡,内存512MB甚至256MB,跑个MySQL加PHP就天天报警?本站监控篇教过怎么看内存,这篇教怎么救内存:理解free输出里buff/cache的真实含义、判断"内存不足"是真不足还是错觉、给小鸡配一个大小合适的Swap、用systemd给服务加内存上限防住一家独大、以及swapiness参数怎么调才符合"内存不够才用Swap"的本意。最后还有OOM杀手的行为逻辑——知道内核杀进程的顺序,才能在被杀时看懂现场。
一、先学会看:free的输出骗了多少人
free -h
free -h的典型输出里,新手最常犯的错是看到available只剩几十MB就慌了。真正要看的只有available这一列——它才是"现在还能给新进程用多少"。而buff/cache那几个G看起来被"吃掉"了,其实是Linux拿空闲内存做了磁盘缓存,任何进程申请内存时这片区域立刻让位。一句口诀:Linux设计哲学就是"闲着不如缓存",内存利用率高是常态不是病。反过来,如果available持续低于总量的10%、并且swap used还在上涨,这才是真的紧张了。
二、第一刀:把省内存的功夫做在前面
加Swap之前,先把明显的浪费堵掉。三个立竿见影的点:MySQL的innodb_buffer_pool_size默认值对512MB的机器是灾难,降到64M到128M;PHP-FPM的pm.max_children按每个worker吃30到50MB反推,512MB内存给4到6个就顶天了;Nginx的worker_processes超过2个纯属浪费。这套参数怎么配,本站Compose篇和反代篇的配置思路直接沿用。另外定期清一下无用的常驻进程,systemd篇教的systemctl list-units --state=running在这里是清点家底的好工具——每个多跑的服务都是从你那512MB里扣的。
三、给小鸡配Swap:一行命令的事
Swap的本质是拿磁盘当内存的溢出区,慢但救命。先看有没有:
swapon --show
空输出就是没有。建一个1GB的Swap文件:
fallocate -l 1G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile
四条命令分别是:预分配文件、收紧权限(这步不能省,权限不对swapon会拒绝)、格式化为swap、启用。开机自动挂载要写进/etc/fstab:
echo '/swapfile none swap sw 0 0' >> /etc/fstab
大小怎么定有讲究:512MB内存的机器配1GB到2GB Swap很合适,8GB以上的大内存机器基本可以不配——Swap的意义是"极端时刻的缓冲",不是常态运行区。硬盘是对IO最敏感的资源,NVMe上做Swap无伤大雅,机械盘或超售严重的VPS上疯狂swap会拖垮整机,这决定了下一节的参数取向。
四、swappiness:决定Swap什么时候被用
vm.swappiness控制内核把内存页换出到Swap的积极程度,取值0到200(新内核),默认60。对小内存VPS,社区流传两种截然相反的建议:调低(10)是为了尽量用物理内存、只在真不够时才swap;调高是为了主动把闲置页换出去给缓存腾地。个人立场:跑网站数据库的小鸡调到10,让Swap保持在"最后防线"的角色;纯闲置页多、又要跑大文件缓存的场景才考虑默认以上。改法:
sysctl vm.swappiness=10
持久化写进/etc/sysctl.conf,和本站BBR篇的调参流程一模一样。改完cat /proc/sys/vm/swappiness核对,别信感觉信文件。
五、OOM Killer:内核的最后手段,看懂它的杀人逻辑
物理内存和Swap都耗尽时,内核的OOM Killer会选一个进程杀掉自救。它不是随机杀人,而是按oom_score打分:吃内存越多的分越高,root进程和长期运行的服务有减免。被杀时系统日志会留下完整现场:
dmesg -T | grep -i 'killed process' journalctl -k | grep -i oom
找到"Killed process 1234 (mysqld)"这样的记录,恭喜你抓到了元凶——不是MySQL的错,是你的内存预算没给够。排查思路顺着来:先确认是不是被OOM杀的(很多人把应用崩溃怪到代码头上,其实凶手是内核);再看swap used是不是早就顶满了(说明缓冲已经用完);最后要么按第二节收紧各服务的内存上限,要么升配。反复被OOM的机器,加Swap只是续命,根治靠预算重分配。
六、用systemd给每个服务上内存紧箍咒
与其等OOM Killer全场乱杀,不如提前给每个服务划定上限。systemd篇讲过的服务单元里加两行:
[Service] MemoryMax=300M
MySQL这类大户被钉死在300MB内,超了会被systemd掐掉重启,而不是膨胀到把Nginx、SSH全挤出去陪葬。配合Restart=always形成"越界就重启"的自动止损。更精细的还有MemoryHigh(软限制,超了只是限流不杀)适合先观察再收紧。这套玩法的前提是你清楚每个服务的正常水位——本站监控篇的哪吒面板盯几天负载曲线,水位线自然就出来了。
七、压榨极限:zram与zswap
磁盘慢的机器还有一招:内存压缩。zram是在内存里划一块区域做成压缩块设备当Swap用,典型的3:1压缩比意味着1GB物理内存能当接近1.3GB用,代价是CPU占用。小鸡CPU常年闲着,这笔账很划算:
apt install zram-tools
装完配置压缩算法(推荐zstd)和大小,重启服务即生效。zram适合当第一级Swap,磁盘Swap当第二级:内核先把冷页压缩进zram,真的爆了再落盘。8GB内存以上机器完全不需要这套,这是纯小内存玩家的求生技。
八、什么时候该承认内存不够
技术手段用尽后要面对现实:Swap频繁活动、OOM日志每周出现、加内存上限的服务反复被重启——三条中两条就该升配了。内存不足引起的性能衰减是断崖式的,从"稍慢"到"假死"只隔一层Swap。用本站压力测试篇的方法在低峰和高峰各压一次,对比数据,升级决策就有了依据。省钱的尽头是花钱,但至少现在你知道钱花在了刀刃上。
结语
小内存VPS的管理心法一句话:free只看available,服务各戴紧箍咒,Swap是防线不是主战场,OOM日志是事故报告书。把这四条变成肌肉记忆,512MB的小鸡也能稳稳跑起一个像样的站。内存管理说到底是预算管理——每一个字节都该有去处、有上限、有监控,这套思路和本站一贯的"可观测、可约束、可复盘"一脉相承。




