numastat输出需重点看numa_hit和numa_miss:numa_hit越高越好,表示本地节点内存分配成功;numa_miss显著高于numa_hit说明本地内存耗尽或分配失败,跨节点访问失控,易引发OOM和性能下降。

numastat 输出怎么看:重点盯住 numa_hit 和 numa_miss
排查 NUMA 内存不均,numastat 是第一个必须看的命令。它不显示“谁用了多少”,而是告诉你内核在各节点间内存分配的实际行为。关键不是总内存占用,而是跨节点访问是否失控。
执行 numastat -p 查看某个进程(比如 Java 或 PostgreSQL)的 NUMA 行为,重点关注两列:
-
numa_hit:在本节点成功分配到内存的次数 —— 越高越好 -
numa_miss:本想在本地节点分配,但失败,被迫去其他节点分配的次数 —— 这个值一旦显著高于numa_hit,说明本地节点内存已耗尽或无法满足分配请求
如果看到某进程的 node0 的 numa_miss 占比超过 20%,基本可以断定 node0 内存已成瓶颈,而 node1 可能还空着 60%。这时候 free -h 看整机 available 依然充足,但 OOM Killer 已经开始杀进程了 —— 因为申请内存时指定的 preferred node 没有可用页,内核又不允许 fallback 到其他节点(取决于 vm.zone_reclaim_mode 和进程策略)。
为什么 top/ps 看不到 NUMA 问题:RSS 和 VIRT 都是假象
top 和 ps aux --sort=-%mem 显示的 RSS 是所有物理页的总和,不管这些页落在哪个 NUMA 节点;VIRT 更是虚拟地址空间,完全不反映实际物理分布。所以你可能看到一个进程 RSS 占了 8G,但其中 7.5G 其实全挤在 node0,而 node1 上只有 500M —— 这种严重倾斜,top 根本不报。
真正要定位,得结合:
-
numastat -p:确认该进程是否跨节点失衡 -
cat /sys/devices/system/node/node*/meminfo:逐节点查真实剩余内存(注意看MemFree和MemAvailable,不是MemTotal - MemUsed) -
cat /proc/:确认进程是否被绑定了 CPU 和内存节点(/status | grep -E "^(Mems_allowed|MMU|Cpus_allowed)" Mems_allowed值如00000001表示只允许 node0)
OOM 发生前的典型信号:dmesg 里没有 “Out of memory”,只有 “page allocation failure”
当 NUMA 不均导致 OOM 时,dmesg 很少出现标准的 Out of Memory: Killed process。更常见的是:
kernel: node 0: page allocation failure: order:0, mode:0xXXXXXX
这个错误说明内核尝试在 node0 分配一页(order=0),但失败了 —— 不是因为整机没内存,而是 node0 的 zone 里没有连续可用页(哪怕 MemAvailable 还剩 1G)。此时 vmstat 1 可能看到 pgpgin/pgpgout 突增,pgmajfault 也明显升高,这是跨节点访问引发的代价。
容易踩的坑:
- 只查
/var/log/messages,漏掉dmesg -T | tail -50的实时内核日志 - 以为 swap 启用就能缓解 NUMA 不均 —— 实际上 swap 分区通常只建在 node0,跨节点换入换出反而加剧延迟
- 用
taskset绑 CPU 却没同步绑内存:taskset -c 0-3 ./app只绑了 CPU,进程仍可能从 node1 分配内存
临时止血和长期规避:numactl 是最直接的干预手段
发现某进程因 NUMA 不均频繁触发分配失败,最快上线修复方式是用 numactl 强制其与 CPU、内存同节点绑定:
numactl --cpunodebind=0 --membind=0 ./your_app
这比改代码或 JVM 参数见效快得多。但要注意:
-
--membind=0是硬性限制,如果 node0 内存真不够,进程会直接malloc失败退出,而不是 fallback;生产环境建议先试--preferred=0(优先但可 fallback) - 容器场景下,
docker run --cpuset-cpus="0-3" --memory=4g不等于 NUMA 感知,必须显式加--oom-kill-disable+numactl启动命令,或使用runc的resources.numa_policy配置 -
numastat的other_node列如果持续增长,说明有大量跨节点共享内存(如 tmpfs、POSIX shm),这类资源不会出现在单个进程的smaps里,得单独用ipcs -m和find /dev/shm -ls排查
NUMA 问题最难缠的地方在于:它不体现为“内存总量不足”,而是一种空间错配。同一台机器,free 显示还有 10G 可用,但只要某个节点被撑满,新分配就会失败 —— 这种“局部饥饿”比全局缺内存更难被监控系统捕获。











