凌晨两点,一辆4核8GB的VPS突然被监控告警:可用内存只剩几十MB,业务请求同时超时。管理员重启服务后看似恢复,几小时后却再次触顶。此时最危险的做法,就是把问题笼统归为“内存泄漏”,或者直接清缓存、重启机器了事。
如果你正在选机器,或者想先把线路和配置跑通再谈长期方案,可以先看看这几家的线路说明和技术参数:云途(全球云服务器),先看清带宽线路、流量策略和退款条款,再决定要不要迁。
缓存回收、匿名页增长与内存泄漏并非同一件事
Linux内存并非一个只能不断扩张的水池。文件缓存通常属于可回收内存,内存紧张时内核可以丢弃缓存页;脏页则先写回磁盘。匿名页主要承载进程堆栈和运行时数据,不能像文件缓存一样直接丢弃,只能依靠回收或换出释放。判断的第一步,是区分缓存、匿名页、slab与进程实际占用。

若缓存回收是主因,可用内存和缓存会在压力出现后重新上升,匿名页总量基本稳定,进程RSS没有持续攀升,内存PSI的some压力也只是短暂升高。这类回收虽然可能造成短时延迟,但并不等于业务进程正在无限占用内存。
真正的内存泄漏通常表现为同一进程或一组进程的匿名页、RSS、PSS连续增长,缓存回收后可用内存仍无法恢复。内核slab增长也可能制造类似现象,因此不能只看系统总内存,还要结合smaps_rollup、进程RSS以及容器或服务的内存统计逐层确认。
用PSI、交换活动和OOM日志锁定根因
交换抖动的特征不是“用了Swap”,而是持续发生交换换入换出:进程刚换入就再次被换出,major fault升高,PSI的some和full持续累积,CPU负载与接口延迟同步上升。若Swap数值很高却没有明显换入换出和压力停滞,可能只是历史遗留,不能单独据此定罪。

排查时可每分钟保存/proc/pressure/memory、vmstat、进程RSS/PSS和memory.stat,再对齐交换速率与业务延迟。使用随身服务器持续记录这些快照,可避免只看到OOM发生后的残留现场;重点观察PSI上涨前后,究竟是缓存下降、匿名页上升,还是换入换出形成循环。
随后检查内核日志和cgroup的memory.events,记录OOM发生时间、被终止进程及所属服务。若OOM前匿名页持续增长,可优先怀疑泄漏;若PSI达到full且Swap高速往返,则更像回收能力不足导致的抖动;若缓存骤降后内存恢复,则更接近正常缓存回收。不要用清缓存代替归因,也不要把禁用Swap当作修复方案。
从内存压力停滞追到匿名页回收
内存PSI中的some stall只表示任务因等待内存推进而发生停顿,并不能证明匿名页正在有效回收,也不能单独判定OOM。匿名页没有可回写的后备存储,通常只能转入swap;当swap空间、swap页或回收线程受限时,内存压力停滞会持续存在。此时即使系统仍有free内存,也可能因回收无法及时完成而出现延迟尖峰。
定位应沿cgroup层级查看memory.stat中的anon、file、swap与pgscan、pgsteal,并结合memory.events的high、max、oom计数。若父级未超限而子级接近max,问题更可能在子级限额;若pgscan很高但pgsteal不增长,则应检查swap、NUMA节点和脏页,而不是继续加内存。host与容器必须分别取证,否则会误判触发OOM的边界。

用时间线区分交换换入换出与OOM
先用同一时间轴对齐vmstat的pswpin、pswpout、PSI的some、内存回收速率和业务延迟。换入换出同时升高,说明工作集超过可用内存,存在交换换入换出抖动;只有换出而无换入,可能是冷页被挤出,并不等于当前正发生抖动。随后核对dmesg或journal中的OOM日志、memory.events的oom_kill,以及被杀进程的cgroup和峰值,确认是否真的发生了OOM事件归因。
常见坑包括把RSS全部视为匿名页、把free很低直接等同于泄漏,以及认为swappiness设为0就完全禁用swap。共享页、文件缓存和内核记账都会影响数字;单纯扩swap可能掩盖限额错误并延长抖动,单纯重启则会丢失现场。判断时应寻找“增长快、限额近、回收失败、发生OOM”的完整证据链。
可执行检查清单:①连续采集10秒与1分钟PSI,保存some、full和mem stall;②记录cgroup的memory.current、memory.stat、memory.events;③每分钟采样vmstat及pswpin、pswpout;④定位增长最快的进程、线程与容器;⑤检查swap余量、NUMA分布、脏页和回收线程状态;⑥按UTC时间关联内核OOM日志与业务延迟;⑦先修正限额或泄漏,再评估扩容和swap调整,并使用同一负载复测验证。


喜欢
顶
难过
囧
围观
无聊





