NUMA架构对服务器性能的基础影响
现代多路服务器普遍采用NUMA(Non-Uniform Memory Access)架构,每个CPU插槽拥有本地内存控制器,访问本地节点的内存延迟远低于跨节点访问。在双路EPYC或Xeon服务器上,本地内存访问延迟约80-120ns,而跨节点访问延迟可达150-250ns,差异超过一倍。数据库、消息队列等内存密集型工作负载如果忽视NUMA拓扑,性能损失可达20%-40%。
NUMA节点的数量取决于物理CPU插槽和CCX/CHM布局。AMD EPYC 9004系列处理器每颗CPU包含4个CCD,每个CCD包含2个Core Complex,单颗CPU自身就呈现4节点NUMA拓扑;双路配置下系统呈现8个NUMA节点,跨节点访问链路更为复杂。
NUMA拓扑发现与延迟矩阵分析
调优的第一步是准确理解系统的NUMA拓扑:
# 查看NUMA节点与CPU亲和性
numactl --hardware
# 查看每个NUMA节点的内存使用
numastat -m
# 安装并测量节点间延迟矩阵
apt install numactl latency-topology
# 或使用Intel Memory Latency Checker
./mlc --loaded_latency -X
Intel MLC的输出会给出每对NUMA节点之间的内存访问延迟矩阵。典型双路Xeon Sapphire Rapids的延迟矩阵:
Numa node 0: 82ns (local)
Numa node 1: 145ns (remote, same socket)
Numa node 2: 195ns (remote, cross socket)
Numa node 3: 190ns (remote, cross socket)
跨Socket访问延迟比同Socket跨节点高出约35%-50%,这是因为跨Socket需要经过UPI/XGMI互连链路。了解这个矩阵是后续所有调优决策的基础。
进程与内存绑定的NUMA策略
Linux提供了numactl命令来控制进程的NUMA亲和性策略,核心参数包括:
--cpunodebind=N:将进程绑定到NUMA节点N的CPU核心上执行--membind=N:限制进程只能在NUMA节点N分配内存--preferred=N:优先在节点N分配内存,不足时回退到其他节点--interleave=all:在所有节点间交叉分配内存
不同场景的最优策略:
# MySQL数据库:绑定到单节点,避免跨节点访问
numactl --cpunodebind=0 --membind=0 mysqld --defaults-file=/etc/mysql/my.cnf
# Redis实例:绑定到单节点,充分利用本地内存带宽
numactl --cpunodebind=1 --membind=1 redis-server /etc/redis/redis.conf
# 多线程应用(如Java JVM):交叉分配保证容量
numactl --interleave=all java -Xms32g -Xmx32g -jar app.jar
关键原则是:内存密集型单实例应用尽量绑定到单节点(membind),多实例部署时每个实例独占一个节点,避免内存竞争和跨节点访问。
MySQL的NUMA优化实战
MySQL是NUMA敏感型应用的典型代表。InnoDB Buffer Pool默认在所有NUMA节点间分配内存,导致大量跨节点访问。优化方案:
# 1. 绑定到NUMA节点0
numactl --cpunodebind=0 --membind=0 mysqld &
# 2. 配置Buffer Pool实例数等于NUMA节点数
[mysqld]
innodb_buffer_pool_instances = 4
innodb_buffer_pool_size = 64G
# 3. 开启NUMA感知的内存分配(MySQL 8.0+)
[mysqld]
innodb_numa_interleave = ON
实测在双路EPYC 9654(192核/4NUMA节点)服务器上,48GB Buffer Pool场景,TPS从绑核前的28,000提升到绑核后的36,500,提升幅度约30%。提升来源主要是减少了Buffer Pool页面扫描时的跨节点访存延迟。
中断亲和性与网卡NUMA对齐
网络密集型场景中,网卡中断处理如果发生在远端NUMA节点,会引入额外的跨节点延迟。高吞吐场景需对齐网卡与处理线程的NUMA位置:
# 查看网卡所在NUMA节点
cat /sys/class/net/eth0/device/numa_node
# 使用set_irq_affinity脚本设置中断亲和性
./set_irq_affinity 0 eth0
# 使用DPDK绑定网卡到特定NUMA节点
dpdk-devbind -b vfio-pci 0000:3b:00.0
numactl --cpunodebind=0 --membind=0 ./dpdk-app -l 0-15
10G网卡场景下,中断亲和性优化可使单连接延迟降低15-20微秒,P99延迟降低约30%。25G/100G网卡场景效果更为显著。
内核参数与透明大页的NUMA影响
透明大页(THP)在NUMA环境下行为需要特别关注。THP的khugepaged守护进程在合并页面时可能将跨节点的4KB页面合并到远端节点的大页中,反而增大延迟。建议内存密集型应用使用显式大页:
# 关闭透明大页的defrag(保留THP但禁用同步整理)
echo never > /sys/kernel/mm/transparent_hugepage/defrag
# 分配显式大页并绑定到NUMA节点
echo 8192 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 8192 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
# MySQL使用大页
[mysqld]
large-pages
显式大页在分配时就遵循NUMA策略,不会出现THP跨节点合并的问题。对于Oracle、PostgreSQL等数据库同样适用。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/linux-fu-wu-qi-numa-jia-gou-diao-you-yu-kua-jie-dian-nei/