服务器虚拟机内存不足,先别急着加内存条或升级配置多数情况下,问题出在缓存占用、进程泄漏、超分策略不合理这三处,按"先定位、再瘦身、后调度、最后才扩容"的顺序处理,往往能省下真金白银并让性能回到正常水位。
内存报警这事儿,运维同学都不陌生:监控面板一片飘红,业务方催着要结果,采购流程又走不完,可真登上去一看,free -m 里的 available 还有一大截,buff/cache 占了小一半,所以第一步永远不是扩容,而是把账算清楚。
虚拟机内存不足怎么排查:先分清真缺内存还是配置浪费
排查的核心是区分"应用真的吃掉了内存"和"内存被系统拿去干别的了",这两者的处理方式完全相反,搞混了就容易白花钱。
三条命令快速定位内存去向
登录虚拟机后,按顺序跑下面几条,基本十分钟内能有结论:
free -m:看 available 而不是 free,Linux 会把空闲内存拿去做页缓存,free 低不代表内存紧张,available 才是真正可用的量。ps aux --sort=-%mem | head -20:按内存占用排序看前 20 个进程,重点看 RSS 列,如果某个 Java 或 Python 进程的 RSS 持续上涨不回落,大概率是内存泄漏。cat /proc/meminfo | grep -i slab:Slab 占用异常高,通常是内核对象(dentry、inode 缓存)堆积,属于典型的"看着像内存不足,其实是缓存没回收"。
再补一条 vmstat 1 5,看 si/so 两列,swap 换入换出频繁,说明物理内存确实吃紧;如果这两列长期为 0,那内存压力其实不大。
常见假性内存不足的三种情况
- 页缓存占满:数据库、文件服务器这类 IO 密集型业务,buff/cache 占到总内存的较大比例属于正常现象,内核会在需要时自动回收,手动执行
echo 1 > /proc/sys/vm/drop_caches只是临时清缓存,治标不治本,还会让后续读性能短暂下降。 - 监控口径不对:有些监控模板直接采 free 值做告警,导致天天误报,业内通行做法是改用 available 或者 memAvailable 指标。
- 虚拟机配置给多了但没开 balloon:宿主机上分配了 16G,虚拟机里实际只用 4G,剩下 12G 被"锁"住,这种情况在自建虚拟化环境里相当普遍。
从虚拟机内部做减法和瘦身
确认是真吃内存之后,先在虚拟机内部动手,成本最低,见效也快。
服务进程层面的内存回收
针对不同运行时,手段不一样:
- JVM 应用:检查
-Xmx是否设得过大,容器或虚拟机内存的 60% 到 70% 是比较稳妥的堆上限,再看 GC 日志,Full GC 后老年代仍然居高不下,那才是真需要更多内存。 - Nginx/PHP-FPM:
pm.max_children乘以单进程内存就是峰值占用,很多人配完就不管了,进程数远超实际并发需要。 - MySQL:
innodb_buffer_pool_size是最大头,一般设成物理内存的 50% 到 70%,但如果同一台机器上还跑了别的服务,这个值就必须往下压。
页缓存与 Swap 的正确用法
vm.swappiness 的默认值通常是 60,对于数据库类业务偏高,调到 10 左右可以减少不必要的换出,但要注意,如果内存本来就紧张,把 swappiness 调低反而可能触发 OOM Killer,这时更该做的是加内存或者减服务。
Swap 分区不建议直接关掉,保留 2G 到 4G 的 swap,在内存峰值来临时能给系统一个缓冲,避免进程被直接杀掉,前提是 swap 放在 SSD 上,机械盘上的 swap 会让性能雪崩。
内核参数调优
几个值得关注的参数:
vm.overcommit_memory:设成 1 允许超量分配,适合 Redis 这类会 fork 子进程的场景,但会放大 OOM 风险。kernel.pid_max和vm.max_map_count:容器化环境下经常需要调高,间接影响内存映射的稳定性。- 透明大页(THP):对数据库类负载,行业共识认为关闭或设为 madvise 更稳妥,可以避免内存碎片和延迟抖动。
KVM 与 VMware 内存超分哪个更稳,取决于业务形态
超分是宿主机层面的资源调度手段,用好了能显著提升密度,用不好就是互相踩踏。
内存超分比例的合理区间
超分不是越高越好,常见做法是 Web 类、无状态服务可以做到 1:1.5 甚至更高,数据库和缓存类服务建议控制在 1:1.2 以内,甚至不超分,超分的前提是各虚拟机的内存峰值错开,如果所有业务都在同一时间段冲高峰,超分就是给自己埋雷。
两种主流方案的技术差异
| 对比维度 | KVM | VMware |
|---|---|---|
| 内存回收机制 | Balloon 驱动 + KSM 页合并 | Balloon + 透明页共享 |
| 超分粒度 | 依赖 guest 内驱动配合 | 管理端策略更细 |
| 监控手段 | virsh memtune、virsh dommemstat | esxtop 内存页、vCenter 告警 |
| 适用场景 | 开源栈、成本敏感型 | 混合负载、需要成熟管理界面 |
简单说,KVM 更灵活、成本低,但调优靠人;VMware 的工具链更完整,超分策略可视化程度高,选择时看团队的技术栈和维护能力,而不是单纯比参数。
CPU 与内存配比失衡的连锁反应
一个常被忽略的点:vCPU 给得太多,内存给得太少,虚拟机内部会出现大量线程争抢,内存分配器压力上升,表现出来就是"内存不够用",通用业务 vCPU 与内存的比例在 1:2 到 1:4 之间比较合理,数据库类可以到 1:8。
电商大促场景下,内存吃紧的应急三步走
场景类问题最考验预案,以大促为例,内存压力通常在开抢后十几分钟内集中爆发。
大促前:压测与预留水位
- 用和生产同规格的虚拟机做全链路压测,记录内存峰值,按峰值的 1.3 倍预留。
- 提前把非核心服务(日志采集、监控 agent、离线任务)的采样频率调低,能省出可观的内存。
- 检查是否所有虚拟机都开了内存热添加,KVM 下需要配置
maxMemory和 slots。
大促中:限流降级与热迁移
内存告警触发后,优先做的是降级而不是扩容:关闭详情页的推荐缓存、下调连接池上限、临时关闭部分异步任务,这些动作几分钟内生效,确实需要迁移时,virsh migrate --live 支持在线热迁移,但要注意目标宿主机必须有足够余量,否则只是把问题搬家。
大促后:复盘与容量规划
把大促期间的内存曲线和平时基线对比,找出增长最快的服务,如果某个服务的内存年增长率明显高于业务增速,基本可以判定存在优化空间,而不是简单加配置。
云服务器虚拟机内存扩容多少钱?先把扩容和优化的账算清
到了真要扩容这一步,就得算成本了,不同部署形态的账差别很大。
云上与自建的成本差异
公有云的按量付费实例,内存从 8G 升到 16G,每月增加的费用因厂商和地域而异,通常是原规格价格的较大比例,包年包月能便宜不少,但灵活性差,自建机房的边际成本主要在内存条采购和宿主机余量,单条 DDR4 内存的价格近年来波动明显,采购前建议比价。
一个常被忽视的成本是"过度预留":买了 32G 实际只用 12G,这部分浪费按年算下来并不小,定期做容量回收,比一次性扩容更划算。
北京IDC机房与公有云的内存成本差异
以北京地区为例,自建托管模式下,一台 16 核 64G 的物理机可以切出多台虚拟机,单台虚拟机的内存成本折算下来通常低于同规格的公有云实例,尤其适合长期稳定运行的业务,但自建需要承担硬件折旧、电费和运维人力,业务波动大时反而不划算,选择的关键是看负载的稳定性:负载平稳、周期长,自建更省;负载波动大、需要弹性,公有云更合适。
Q&A:服务器虚拟机内存不足常见问题
虚拟机内存占用高但业务不卡,需要处理吗?
先看 available 和 swap 使用率,available 充足、swap 换入换出接近零、业务响应正常,那说明内存用在了页缓存上,属于健康状态,不需要处理,强行清缓存反而会降低 IO 性能,只有当 available 长期低于总内存的 10% 且伴随 swap 频繁读写时,才需要介入。
内存超分后虚拟机之间会互相影响吗?
会,超分本质是共享物理内存,当多个虚拟机同时冲高峰,宿主机触发内存回收,Balloon 驱动会挤压各虚拟机的可用内存,表现就是已经在跑的服务突然变慢甚至被 OOM,缓解办法一是控制超分比例,二是给关键业务设置内存预留(KVM 的 memtune 或 VMware 的 reservation),保证这部分内存不被回收。
加内存和优化配置,哪个性价比更高?
取决于瓶颈在哪,如果排查后确认是进程泄漏或者配置冗余,优化几乎零成本,优先做;如果是业务量实打实增长了,优化空间已经榨干,那就是扩容,据工信部相关统计口径,企业 IT 支出中硬件采购占比较大,而相当一部分资源浪费来自配置不合理,先做一轮容量梳理再决定是否采购,通常能减少不必要的投入。