Linux内核学习轨迹第五部:内存管理相关的问题排查、调优与故障定位 (第十四小节)
2026/6/9 1:22:24 网站建设 项目流程

14. 内存管理相关的问题排查、调优与故障定位

内存管理相关的问题是线上服务最常见、也最难排查的问题,比如内存泄漏、内存抖动、OOM误杀、系统卡顿、性能下降等。本章节基于Linux 6.6 LTS内核,总结内存管理问题的排查流程、常用工具、调优最佳实践、常见故障的定位与解决。

14.1 内存管理问题的排查流程

当系统出现内存管理相关的问题时,按照以下流程排查:
1. 确认问题现象
├→ 内存泄漏:系统的可用内存持续下降,MemAvailable持续减少
├→ 内存抖动:si/so持续很高,iowait很高,业务吞吐量急剧下降
├→ OOM误杀:核心业务进程意外退出,dmesg中有OOM记录
├→ 系统卡顿:pgscan_direct/pgsteal_direct持续很高,kswapd的CPU使用率很高
└→ 性能下降:dTLB-load-misses/dTLB-store-misses持续很高,内存访问延迟增加
2. 收集系统信息
├→ 全局内存信息:free -h、cat /proc/meminfo、vmstat 1、sar -r 1
├→ 进程级内存信息:top、ps aux --sort=-%mem、pidstat -r 1 -p
├→ 内核日志:dmesg、journalctl -k
├→ 内存回收信息:cat /proc/vmstat | grep pgscan | pgsteal | kswapd
├→ 页缓存信息:cat /proc/meminfo | grep Cached | Dirty | Writeback
├→ Swap信息:swapon --show、cat /proc/meminfo | grep Swap
├→ 大页信息:grep Huge /proc/meminfo、ls -l /sys/kernel/mm/hugepages/
└→ memcg信息(如果使用):cat /sys/fs/cgroup/memory//memory.usage_in_bytes、memory.events
3. 定位问题根源
├→ 内存泄漏:用Valgrind、AddressSanitizer、perf mem定位泄漏位置
├→ 内存抖动:确认进程的工作集大于可用物理内存,或者swappiness设置过高
├→ OOM误杀:确认被杀死进程的oom_score_adj设置不合理,或者memcg的内存限制设置过低
├→ 系统卡顿:确认min_free_kbytes设置过低,或者watermark_scale_factor设置过低,导致直接回收频繁触发
└→ 性能下降:确认TLB miss的次数很高,或者大页配置不合理
4. 解决问题
├→ 内存泄漏:修复泄漏位置,或者扩容物理内存
├→ 内存抖动:扩容物理内存,或者调小swappiness,调大min_free_kbytes
├→ OOM误杀:调整核心业务进程的oom_score_adj,或者使用memcg限制进程的内存占用
├→ 系统卡顿:调大min_free_kbytes和watermark_scale_factor,提前触发kswapd异步回收
└→ 性能下降:启用大页,或者调整大页的配置
5. 验证问题是否解决
├→ 监控系统的内存使用情况,确认问题不再出现
├→ 测试应用的吞吐量和延迟,确认性能恢复
└→ 记录问题的排查流程和解决方案,避免再次出现

14.2 内存管理问题的常用工具

14.2.1 全局内存监控工具

  1. free:查看系统的内存使用情况,包括总内存、已用内存、空闲内存、buff/cache、可用内存;
  2. /proc/meminfo:查看系统的详细内存信息,包括MemTotal、MemFree、MemAvailable、Buffers、Cached、Dirty、Writeback、SwapTotal、SwapFree、AnonPages、Mapped、Slab、PageTables、VmallocUsed、HugePages_Total、HugePages_Free、HugePages_Rsvd、Hugepagesize、AnonHugePages;
  3. vmstat:查看系统的虚拟内存统计信息,包括r(运行队列长度)、b(不可中断睡眠队列长度)、si(swap换入)、so(swap换出)、bi(块设备读入)、bo(块设备写出)、in(中断)、cs(上下文切换)、us(用户态CPU使用率)、sy(内核态CPU使用率)、id(空闲CPU使用率)、wa(iowait);
  4. sar:系统活动报告工具,查看系统的历史内存使用情况,包括-r(内存使用情况)、-B(页缓存统计)、-W(swap统计)、-S(swap空间统计)。

14.2.2 进程级内存监控工具

  1. top:查看系统的进程信息,按f可以勾选内存相关的字段,包括%MEM(内存使用率)、VIRT(总虚拟内存)、RES(物理内存)、SHR(共享内存)、nDRT(TLB miss的次数)、SWAP(swap占用);
  2. ps:查看系统的进程信息,ps aux --sort=-%mem可以按内存使用率降序排列;
  3. pidstat:查看进程的详细内存信息,pidstat -r 1 -p 可以查看进程的缺页异常次数、虚拟内存大小、物理内存大小;
  4. /proc/pid/status:查看进程的详细内存信息,包括VmPeak(峰值虚拟内存)、VmSize(当前虚拟内存)、VmLck(锁定内存)、VmHWM(峰值物理内存)、VmRSS(当前物理内存)、RssAnon(匿名页物理内存)、RssFile(文件页物理内存)、RssShmem(共享内存物理内存)、VmData(数据段大小)、VmStk(栈大小)、VmExe(代码段大小)、VmLib(共享库大小)、VmPTE(页表大小)、Threads(线程数);
  5. /proc/pid/maps:查看进程的虚拟内存区域(VMA),包括虚拟地址范围、权限、偏移、设备、inode、路径;
  6. /proc/pid/smaps:查看进程的虚拟内存区域的详细信息,包括每个VMA的大小、物理内存大小、共享内存大小、私有内存大小、脏页大小、交换页大小、缺页异常次数。

14.2.3 内存泄漏定位工具

  1. Valgrind:内存调试工具,valgrind --leak-check=full ./your_program可以定位内存泄漏的位置、泄漏的大小、泄漏的次数;
  2. AddressSanitizer:内存错误检测工具,编译时加上-fsanitize=address -g,运行程序可以定位内存泄漏、内存越界、释放后使用、重复释放等问题;
  3. perf mem:性能分析工具,perf mem record ./your_program可以记录内存访问事件,perf mem report可以查看内存访问的统计信息,定位内存泄漏的位置;
  4. mtrace:GNU C库的内存调试工具,在程序开头调用mtrace(),结尾调用muntrace(),运行程序可以生成内存分配/释放的日志,定位内存泄漏的位置。

14.2.4 内存回收与OOM排查工具

  1. dmesg:查看内核日志,OOM时会打印详细的OOM记录;
  2. /proc/vmstat:查看内存回收的统计信息,包括pgscan_kswapd(kswapd扫描的页数量)、pgscan_direct(直接回收扫描的页数量)、pgsteal_kswapd(kswapd成功回收的页数量)、pgsteal_direct(直接回收成功回收的页数量)、kswapd_steal(kswapd回收的页数量)、oom_kill(OOM杀死的进程数量);
  3. /sys/fs/cgroup/memory//memory.events:查看memcg的OOM统计信息;
  4. crash:内核崩溃分析工具,分析内核coredump,定位OOM的原因。

14.2.5 大页与TLB排查工具

  1. perf stat:性能分析工具,perf stat -e dTLB-load-misses,dTLB-store-misses,iTLB-load-misses ./your_program可以跟踪TLB miss的次数;
  2. /proc/cpuinfo:查看CPU的信息,确认是否支持1GB大页(需要pdpe1gb标志);
  3. grep Huge /proc/meminfo:查看大页的使用情况;
  4. ls -l /sys/kernel/mm/hugepages/:查看大页的配置。

14.3 内存管理的调优最佳实践

我们总结了内存管理的调优最佳实践,覆盖绝大多数生产环境场景:

1.全局内存调优:

  1. 调大min_free_kbytes,预留更多的空闲内存,避免直接回收,建议设置为物理内存的1%~5%,比如32GB物理内存设置为1GB(1048576);
  2. 调大watermark_scale_factor,提前触发kswapd异步回收,建议设置为100;
  3. 调小swappiness,数据库等延迟敏感的服务设置为0,禁止回收匿名页;内存充足的场景设置为10,优先回收文件页;
  4. 调大vfs_cache_pressure,内存不足的场景设置为200,优先回收dentry/inode缓存;
  5. 启用MGLRU,Linux 6.0+默认启用,回收效率提升30%~200%;
  6. 调小mglru_gen_interval_ms,延迟敏感的服务设置为500,更准确地识别工作集。

2.Swap调优:

  1. 生产环境优先使用SSD作为swap设备,性能提升几十倍;
  2. 创建多个swap分区,分布在不同的SSD上,提升swap的IO带宽;
  3. 调大page-cluster,机械硬盘设置为5(32页),SSD设置为0(1页);
  4. 调小swappiness,避免swap抖动;
  5. 不要把swap分区和数据分区放在同一个磁盘上。

3.OOM调优:

  1. 调整核心业务进程的oom_score_adj,设置为-1000,禁止被OOM杀死;
  2. 调整内存泄漏的后台进程的oom_score_adj,设置为1000,优先被OOM杀死;
  3. 使用memcg限制进程的内存占用,避免单个进程占用过多的内存;
  4. 调大min_free_kbytes和watermark_scale_factor,提前触发kswapd异步回收,避免OOM;
  5. 高可用集群可以设置panic_on_oom=1,OOM时系统崩溃,由集群管理软件重启节点。

4.大页调优:

  1. 生产环境优先使用静态大页,性能稳定,无内存碎片;
  2. 绝大多数场景使用2MB大页,TLB命中率已经很高,灵活性好;
  3. 预留应用需要的大页数量+10%的缓冲,不要预留过多;
  4. 大页分配时优先从本地NUMA节点分配;
  5. 不要在使用大页的应用中使用swap;
  6. 数据库等延迟敏感的服务禁用THP,或设置为madvise。

5.监控调优:

  1. 用Prometheus+Grafana监控系统的内存使用情况,包括MemAvailable、SwapFree、kswapd的CPU使用率、pgscan_direct/pgsteal_direct、si/so、Dirty/Writeback;
  2. 监控进程的内存使用情况,包括VmRSS、RssAnon、RssFile、Threads;
  3. 监控大页的使用情况,包括HugePages_Free、AnonHugePages;
  4. 监控memcg的使用情况,包括memory.usage_in_bytes、memory.events;
  5. 设置告警规则,提前发现内存不足的问题,扩容物理内存或优化程序的内存占用。

14.4 常见故障的定位与解决

14.4.1 内存泄漏

现象:系统的可用内存持续下降,MemAvailable持续减少,buff/cache占用很高,drop_caches后MemAvailable很快又下降。
排查流程
  1. 用free -h确认MemAvailable持续下降;
  2. 用ps aux --sort=-%mem找到内存占用最高的进程;
  3. 用cat /proc/pid/status查看进程的VmRSS和RssAnon,确认RssAnon持续增长;
  4. 用Valgrind、AddressSanitizer、perf mem定位内存泄漏的位置;
  5. 修复内存泄漏的位置。
临时解决方案
  1. 重启内存泄漏的进程;
  2. 扩容物理内存。

14.4.2 内存抖动

现象:si/so持续很高,iowait很高,业务吞吐量急剧下降,CPU的wa很高。
排查流程
  1. 用vmstat 1确认si/so持续很高;
  2. 用top → 按f → 勾选SWAP,找到占用swap最多的进程;
  3. 用cat /proc/pid/status | grep VmRSS查看进程的工作集大小,确认工作集大于可用物理内存;
  4. 检查swappiness的配置,确认是否设置过高。
解决方案
  1. 最根本的解决方案是扩容物理内存;
  2. 调小swappiness,设置为0,禁止回收匿名页;
  3. 调大min_free_kbytes和watermark_scale_factor,提前触发kswapd异步回收;
  4. 优化程序的内存占用,减少工作集的大小。

14.4.3 OOM误杀

现象:核心业务进程意外退出,dmesg中有OOM记录,被杀死的进程是核心业务进程,而不是内存泄漏的后台进程。
排查流程
  1. 用dmesg查看OOM的详细记录;
  2. 查看被杀死进程的oom_score_adj,确认是否设置不合理;
  3. 查看触发OOM的进程的内存占用,确认是否是内存泄漏的进程;
  4. 检查memcg的配置(如果使用),确认是否设置过低。
解决方案
  1. 调整核心业务进程的oom_score_adj,设置为-1000;
  2. 调整内存泄漏的后台进程的oom_score_adj,设置为1000;
  3. 使用memcg限制进程的内存占用;
  4. 调大min_free_kbytes和watermark_scale_factor,避免OOM;
  5. 修复内存泄漏的后台进程。

14.4.4 系统卡顿

现象:系统周期性卡顿,pgscan_direct/pgsteal_direct持续很高,kswapd的CPU使用率很高,业务延迟增加。
排查流程
  1. 用vmstat 1确认pgscan_direct/pgsteal_direct持续很高;
  2. 用cat /proc/vmstat | grep pgscan确认直接回收的次数很多;
  3. 检查min_free_kbytes和watermark_scale_factor的配置,确认是否设置过低;
  4. 检查脏页回写的配置,确认dirty_background_ratio和dirty_ratio的差值是否太小。
解决方案
  1. 调大min_free_kbytes,设置为物理内存的1%~5%;
  2. 调大watermark_scale_factor,设置为100;
  3. 调大dirty_background_ratio和dirty_ratio的差值,比如dirty_background_ratio=10,dirty_ratio=30;
  4. 调小dirty_writeback_centisecs,让回写线程更频繁的唤醒;
  5. 启用MGLRU,提升回收效率。

14.4.5 性能下降

现象:应用的吞吐量下降,延迟增加,dTLB-load-misses/dTLB-store-misses持续很高。
排查流程
  1. 用perf stat -e dTLB-load-misses,dTLB-store-misses,iTLB-load-misses ./your_program确认TLB miss的次数很高;
  2. 检查大页的配置,确认是否启用;
  3. 检查THP的配置,确认是否设置为never或madvise;
  4. 检查进程的虚拟内存区域,确认是否可以合并为大页。
解决方案
  1. 启用静态大页,预留足够的大页;
  2. 绝大多数场景使用2MB大页,内存密集型的应用使用1GB大页;
  3. 数据库等延迟敏感的服务禁用THP;
  4. 优化程序的内存访问模式,提升局部性,减少TLB miss的次数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询