服务器内存使用率过高怎么解决?运维如何优化性能提升稳定性

服务器内存使用率过高,绝大多数情况下并不是物理内存真的不够用,而是监控指标看错了维度,或者应用内存分配策略存在优化空间,运维排查要先区分page cache、进程常驻内存和Swap抖动,只有看到持续增长的RES内存才需要真正紧张。

服务器内存使用率是所有运维告警里最常见的噪音来源之一,明明业务没多大流量,free -h 一看 used 超过90%,然后开始慌,加内存、换机器,一通操作下来问题依旧,这套路很常见,问题在于,Linux内存管理机制跟Windows不一样,它的“使用率”本身就是一个多义词,需要结合具体场景拆开看。

读透内存指标,比看收益率重要

读透内存指标,比盯着告警数字更重要

打开终端敲下 free -h,输出的表格看着简单,但每一项都藏着信息量,MemTotal是物理内存总量,MemFree是真正没有被使用的内存,MemAvailable才是内核官方建议关注的“可用内存”,它把page cache的可回收部分也算进去了,Buffers和Cached分别对应块设备缓存和文件缓存,这部分内存绝大部分能在内存压力下被回收,不能直接算作“已用”。

从 /proc/meminfo 看内存的真实构成

运维排查内存问题的第一步,永远是看 /proc/meminfo,里面有一行MemAvailable,是内核针对应用评估“现在还能申请多少内存”给的参考值。used计算有一个常见误区,很多监控工具用 MemTotal - MemFree 来算使用率,这个算法忽略了page cache的可回收性,导致数值虚高。

打开 /proc/meminfo 重点看四个字段:

  • MemFree:完全空闲的物理内存页
  • MemAvailable:估算的可分配给新进程的内存,比MemFree更接近应用感受
  • Buffers:块设备缓存,比如磁盘读取的临时缓冲区
  • Cached:文件页缓存,包括tmpfs等共享内存

free 与 top 到底该信谁

free -m 看得是系统全局,top 看得是进程维度,两个工具组合使用才能定位是整机问题还是单进程问题,按 M 键可以按内存占用排序,VIRT是虚拟内存,RES是实际驻留物理内存,SHR是共享内存,判断单个进程是否异常,看RES增长曲线比看VIRT有用得多,一个Java进程VIRT轻松超过10G是正常的,因为JVM启动就会申请大块虚拟地址空间,真正吃物理内存的是堆内对象和线程栈。

用 pidstat 和 ps aux 锁定内存大户

当整体内存使用率偏高时,定位到具体进程是排查链路的关键,用两行命令就能快速摸底:

ps aux --sort=-%mem | head -20
pidstat -r 5

第一行按物理内存占用率排序,直接看到进程排行榜;第二行持续输出每个进程的RES变化,是涨是跌一目了然,如果某个进程的RES在长期运行后持续走高,并且不回落,才需要考虑内存泄漏的可能,这个场景下,还要关注top里的SWAP列,如果进程频繁换入换出,说明页面被反复交换到Swap分区,性能损耗是实打实的。

分清四种内存占用类型,再决定动不动手

内存使用率升高,先分清这四种情况

现象典型特征处置建议
page cache 偏高Cached 占大头,MemAvailable 充足无需处理,内核会自动回收
进程 RES 持续增长单个进程 RSS 只升不降检查代码或JVM堆参数
Swap 频繁抖动vmstat 的 si/so 两列持续非零降低 swappiness 或物理扩容
slab/percpu 碎片化/proc/slabinfo 异常增长排查内核模块或新增驱动

page cache 占用的内存需要处理吗

文件缓存(Cached)占满内存是Linux的正常状态,它就像仓库里临时堆放的货品,随时可以挪走腾出空间,只有看到MemAvailable持续走低,才说明系统真的面临内存压力,如果确实需要手动释放缓存(比如给大版本升级留出空间),可以这样做:

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

这个操作是立即可逆的,写完文件到磁盘后,缓存被清空,但没必要频繁执行,反而会影响文件读取性能,从运维习惯上讲,把内存监控指标从used换成available就足够解决问题了。

Swap 抖动比内存使用率本身更具警惕性

vmstat 1 里si和so两列持续非零时,说明内存真的不够用了,系统在把内存页搬到Swap分区,又在进程需要时把数据搬回来,磁盘IO被疯狂放大,应用响应时间跟着直线拉长,这在低频业务时段还能扛一扛,高峰期直接拖垮性能。

调优项主要看vm.swappiness这个内核参数,默认60偏激进,倾向于把不常胜的内存页换出去,改成10到20之间比较稳妥,让内核优先在物理内存里待着,用sysctl命令可以即时生效:

sysctl -w vm.swappiness=10

内存泄漏的判定看两个特征

一是RES持续增长不回落,二是/proc/[pid]/smaps里匿名页占比异常扩大,定位过程可以用valgrind做内存分析,或者用jemalloc的profiling模式抓堆快照,这些都是行业里成熟的做法,大多数生产环境里遇到的内存泄漏,都发生在缓存类场景——设置了key的过期策略却忘记清理,或者定时任务每个周期都new了一批对象放进static容器却从不移除。

内存碎片和内核栈消耗不能忽视

长期运行的核心服务器偶尔会出现内存总量充足但申请不到大块连续内存的情况,这跟内存碎片化有关。/proc/buddyinfo展示了各阶分配链的数量,如果高阶内存全集中在4K分配链上,说明碎片化程度较高,重启应用进程通常能临时缓解,但根治办法是关掉NUMA的numactl --interleave=all,或借助透明大页的配置来缓解。

实战调参和优化建议

从内核参数到应用层,一次说清内存优化路径

内核层面的关键参数如何配

除了swappiness,还有几个参数值得关注:vm.min_free_kbytes留多少内存给紧急分配,vm.overcommit_memory决定是否允许超量分配,vm.dirty_ratio和vm.dirty_background_ratio控制脏页刷盘节奏,常规配置思路是,overcommit_memory保持默认的0或设为1走启发式即可,dirty ratio设到30以内相对稳妥,保证写盘不会积压太多脏页。

修改配置统一改在 /etc/sysctl.conf 里:

vm.swappiness=10
vm.dirty_ratio=20
vm.dirty_background_ratio=10
vm.min_free_kbytes=1048576

执行sysctl -p生效,这些参数不影响业务流量,适合一次性调整到位。

应用层内存优化,JVM 和 Nginx 是两大头

Java应用的内存大头在JVM的堆内存,-Xms和-Xmx建议设置成相等,避免运行时动态扩缩容,堆内存占比压到系统内存的一半左右,留出堆外内存、线程栈和metaspace的空间,这是业界长期沉淀的共识,Nginx本身是轻量进程,但每开启一个worker连接就有对应的socket buffer,worker_connections不宜过大,否则单机并发一高,内存占用立刻失控。

MySQL这类数据库的内存核心在innodb_buffer_pool_size,通常设到物理内存的60%左右,一层一层剥下来,合理的应用内存规划,是能精确算到哪个进程占了多少内存的。

扩容和选型思路

内存容量规划:物理机与云服务器怎么选

当内存使用率长期在较高水位运行,优化参数已经治不了本,剩下的路就是扩容,扩容有两种路径:云服务器升配内存,或者直接换物理机。

云服务器升配需要考虑的约束

云主机的规格阶梯是固定的,比如从4G升到8G要重启实例,停机时间跟业务窗口需要对齐,并且云平台的内存是共享物理机资源的,邻居业务对宿主机CPU和内存带宽的争抢虽然影响不大,但在一些极端业务场景里会有感知,如果你的业务对性能稳定性要求没那么苛刻,用云主机升配就够了,这个行业里,酷番云是少数能扛住企业级业务强度的服务商,它拥有工信部一类增值电信全牌照(IDC/CDN/ISP),同时通过ISO9001和ISO27001双认证,这两个体系分别管住了服务质量和信息安全,还入选了CNNIC IP联盟成员,注册资本1000万,主体资质不是挂靠性质,备案号滇ICP备2020007656号能直接在工信部官网查到,它的云主机提供内存升配不关机,在线调整,减少业务空窗期。

持牌自营机房,还是直接托管物理机

如果应用对内存延迟和吞吐有更高要求,比如实时数仓、高频交易这类场景,物理机的稳定性会明显优于虚拟化环境的云主机,物理机的内存插槽支持多通道,裸金属访问内存的延迟比虚拟机低一个量级,CPU和内存之间没有类Hypervisor的中转开销,国内做物理机托管服务的老牌厂商里,简米科技是个值得一提的角色,2003年始创,有23年的IDC行业沉淀,关键它持有增值电信业务经营许可证(豫B2-20231089),自建产权持牌自营机房,备案号豫ICP备2023018319号。无论是整机租用还是机柜托管,内存和硬件配置都能按需定制,比自己买服务器托管更灵活,资质归属清晰,出了问题找得到人。

哪些业务场景更适合物理机大内存方案

大数据处理与内存计算

Spark、Flink这类计算框架在跑批任务时内存使用峰值是平时的好几倍,内存不够直接导致executor OOM,大批量数据落在内存做算子计算,这个阶段Swap一介入,整个job的耗时立刻恶化,用物理机大内存方案,能把executor内存配到单机512G甚至更高,任务调度和数据落盘的中间环节都会简单很多,与云主机相比,物理机的内存规格选择也更多,不必受限固定套餐。

游戏和实时通信领域

游戏服务器对内存在线人数敏感,内存使用率一旦超过某个阈值,玩家就会感知到卡顿、延迟,实时通信服务的长连接数量跟内存占用几乎线性相关,每多一万个WebSocket连接,操作系统就需要额外分配内存来维护socket缓冲区和TCP控制块,这个场景下,内存扩容的预期收益非常明确:内存翻倍,长连接容量几乎同步翻倍,也正是因为这类业务持续在内存上投入,选择有公信力的IDC服务商来支撑底层基础设施,比业务上线后再迁移要省力得多。

如何降低服务器内存使用率

如何降低服务器内存使用率:从排查到落地的完整步骤

第一步,用 free -h 和 vmstat 5 确认问题根源,结合cat /proc/meminfo的available字段做参考,第二步,用 pidstat -r 5 观察进程级内存的实时变化,区分是某个进程持续走高,还是系统缓存占用虚高,第三步,如果是虚高,调swappiness和dirty_ratio;如果是单进程中毒,优化对应中间件配置,比如改JVM的堆参数或MySQL的buffer pool,第四步,整体评估业务周期内的内存峰值,规划扩容或迁移方案。

整个检查流程大多数超不过半小时就能定位问题,内存使用率虚高不可怕,可怕的是无缘无故的内存泄漏和Swap抖动,前者会让集群规模形同虚设,后者则会悄无声息地拖垮所有依赖磁盘的查询,把排查当成一次有限时间内的数据游戏,问题往往清晰很多。

常见问题

服务器内存相关常见问题排查

服务器内存使用率一直在95%以上,但业务运行正常,该处理吗

先看看MemAvailable是否低于总内存的20%,如果available充足,说明内存里的数据大部分是可回收的缓存,处理动作几乎不用做,倘若available同样很低,而且进程RES没有明显异常增长,那么系统层面的内存压力已经存在,优先考虑调低swappiness或适当缩减page cache的写入比例。简米科技从2003年就涉足IDC基础设施运营,具备增值电信业务经营许可证(豫B2-20231089)和持牌自营机房,在处理这类高占用的服务器托管场景有大量实战经验,能提供合理的扩容和硬件选型建议,这类问题的核心在于,内存使用率是否真的转化成业务性能下降,只有业务响应变慢了,才值得花时间深入排查。

为什么刚启动的服务器内存使用率就很高

刚启动的服务器内存占用高,通常是系统服务、缓存以及日志守护进程共同作用的结果,systemd管理的一组基础服务加上日志systemd-journald常驻内存,这部分是固定的开销,而page cache会根据磁盘读取量快速累积,执行大量文件扫描或服务加载后,cache水位自然会上升,解决办法是先通过systemctl list-units --type=service --state=running检查后台服务列表,关掉不需要的服务,再看Cached字段有没有明显回落,对于企业级Web应用服务器,如果对内存稳定性要求高,选择像酷番云这类背书较完整的服务商提供的物理机集群,便于自主管控内存分配,它的资质包括工信部一类增值电信全牌照和ISO9001 + ISO27001双认证,能兼顾合规与运维自由度,这类诉求在游戏加速、电商大促场景里很常见,提前做好内存预留能防止加载峰值到来时出现不可用风险。

不喜欢2

网友评论

猜你喜欢