NUMA
(Non Uniform Memory Access
)和 UMA
(Uniform Memory Access
)是两种 CPU 相关的硬件架构。在早期的 UMA 架构中,CPU 通过前端总线(FSB,Front Side Bus
)连接到北桥芯片,然后北桥芯片连接到内存,即内存控制器集成在北桥芯片中。外部 IO 设备与南桥芯片相连,南桥芯片与北桥芯片通过内部总线相连。
下图为 UMA 架构图
下图为早期的 UMA 架构主板。图中,靠近 CPU 黄色框线处为北桥芯片,其内部集成了内存控制器,通过 FSB 前端总线与 CPU 互联。靠近 BIOS 电池红色框线处为南桥芯片,集成了外围 IO 设备的控制器(如USB、Audio等),通过内部总线与北桥芯片互联。
100%•75%•50%
总线模型保证了 CPU 的所有内存访问都是一致的,不必考虑不同内存地址之间的差异。优点是资源共享,而缺点是总线争用激烈。随着服务器中 CPU 数量的增多,FSB 总线争用的弊端慢慢越来越明显,成为了系统瓶颈。于是,为了消除 FSB 的瓶颈,Intel 在 Nehalem CPU 上推出了 NUMA 架构。AMD 在引入 64 位 x86 架构时,也实现了 NUMA 架构。
CPU socket
会有一个独立的内存控制器CPU scoket
独立直连到一部分内存,这部分直连内存称为此 CPU 的 “本地内存”。CPU socket
与其直连的 “本地内存”,可称为一个 “Numa Node
”。Quick Path Interconnect
)总线进行连接。CPU 可以通过 QPI 总线访问不与自己直连的 “远程内存
”。Numa Node
中的内存(称为 “远程内存
”),则延迟增加,效率降低。如下图所示,一台服务器包含 2 个处理器、4 个内存块。NUMA 架构将 1 个处理器与 2 个内存块合起来(如将 Processor1
与 Memory1.1
、Memory1.2
结合)称为一个 “NUMA Node
”。如此,这台服务器共有 2 个 NUMA Node
。在物理分布上,NUMA Node
内的处理器和内存块的物理距离更小,因此访问速度也更快。如下图所示,NUMA Node1
的 Processor1
访问 Memory1.1
和 Memory1.2
比访问Memory2.1
和 Memory2.2
更快。所以,使用 NUMA 的模式,如果能尽量保证本 Node 内的 CPU 只访问本 Node 内的内存块,那这样的效率就是最高的。
100%•75%•50%
Linux 提供了一个 NUMA 绑核工具 numactl(默认不安装),在 CentOS 中安装命令如下:
sudo yum install numactl −y
通过 “lscpu
” 命令,可查看系统中的处理器是否为 NUMA 架构。
~]$ sudo lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 64
On-line CPU(s) list: 0-63
Thread(s) per core: 2
Core(s) per socket: 16
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 85
Model name: Intel(R) Xeon(R) Silver 4216 CPU @ 2.10GHz
Stepping: 7
CPU MHz: 2699.981
CPU max MHz: 3200.0000
CPU min MHz: 800.0000
BogoMIPS: 4200.00
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 1024K
L3 cache: 22528K
NUMA node0 CPU(s): 0-15,32-47
NUMA node1 CPU(s): 16-31,48-63
结果显示,系统中包含 2 个 Numa Node
。其中,"0-15,32-47
" 核属于 Numa Node1
、"16-31,48-63
" 属于 Numa Node2
。通过如下的 “numactl --hardware
’’ 也可以验证这一信息。除此之外,”numactl --hardware
’'还展示了每个 Numa Node
的本地内存分配,以及访问本地内存、远程内存的距离(distance)信息。
~]$ sudo numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
node 0 size: 31692 MB
node 0 free: 29048 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
node 1 size: 32234 MB
node 1 free: 30114 MB
node distances:
node 0 1
0: 10 21
1: 21 10
~]$ sudo numactl --show
policy: default
preferred node: current
physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
cpubind: 0 1
nodebind: 0 1
membind: 0 1
示例中显示,当前绑核策略为 "default’’。"default’’ 默认策略为 "--localalloc
’’。内存绑核策略包括:
--localalloc
或者 -l
:进程尝试从本地节点上请求分配内存,如果失败则从其他 Node 上申请内存。--membind=nodes
或者 -m nodes
:规定进程只能从指定的 nodes 上请求分配内存。当在 TiDB 集群的配置文件中为 TiDB/PD/TiKV 指定 numa_node
参数时,即相当于以 membind
策略为 TiDB
组件进行 Numa
绑核。tidb_servers:
- host: 192.168.3.221
ssh_port: 22
port: 4000
status_port: 10080
deploy_dir: /tidb-deploy/tidb-4000
log_dir: /tidb-deploy/tidb-4000/log
numa_node: "0,1"
arch: amd64
os: linux
--preferred=node
:优先从指定 node 请求内存分配,如果获取失败,则尝试其他 node。--interleave=nodes
或者 -i nodes
:规定进程从指定的 nodes 上,以 round robin
算法轮询地请求内存分配。可通过 ·numastat· 查看系统中 ·numa node· 的运行信息。
~]$ numastat
node0 node1
numa_hit 2428976598 1126105874
numa_miss 1226502 259640186
numa_foreign 259640186 1226502
interleave_hit 23412 23575
local_node 2428960674 1126067489
other_node 1242426 259678571
node
节点的内存大小,这个值和另一个 node 的 numa_foreign
相对应。如 node0
的 numa\_miss
与 numa\_node1
的 numa_foreign
相对应。numa_miss
相对应。如 node0
的 numa_foreign
与 numa_node1
的 numa_miss
相对应。很明显,miss 值和 foreign 值越高,就需要考虑 numa 绑定的问题。但是,如果本身内存资源就不足,则可直接禁用 NUMA 特性。
## 将 myapplic 运行在 cpus 0-4、8-12 中
numactl --physcpubind=+0-4,8-12 myapplic arguments
## 将 bigdatabase 运行在所有 cpu node 中,参数为 argments
numactl --interleave=all bigdatabase arguments
## 将 process 运行在 node0,并从 node0、node1 申请内存
numactl --cpunodebind=0 --membind=0,1 process
## 将 process 运行在 node0,并从 node0、node1 申请内存 balancing
numactl --cpunodebind=0 --balancing --membind=0,1 process
## 将 network-server 运行在 eth0 所属的 node 中,并从该 node 中申请内存
numactl --cpunodebind=netdev:eth0 --membind=netdev:eth0 network-server
## 以 node0 为首选,执行 numactl --show
numactl --preferred=0 numactl --show
针对 Oracle、MySQL 数据库,开启 Numa 可能会带来性能问题,因此建议关闭 Numa 特性。可通过如下方式,关闭 Numa:
BIOS:interleave = Disable / Enable
Linux 操作系统,可编辑 /etc/default/grub
文件,在参数 GRUB_CMDLINE_LINUX
的值的末尾,追加上 numa=off
。以 CentOS7 为例。
## 修改 grub 文件
~]# cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=ol/root rd.lvm.lv=ol/swap rhgb quiet numa=off"
GRUB_DISABLE_RECOVERY="true"
## 重新生成启动配置
~]# cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.bak
~]# cp /boot/efi/EFI/redhat/grub.cfg /boot/efi/EFI/redhat/grub.cfg.bak
~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1127.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1127.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-0ffe1c969db740f3bf50f4567ee5fba5
Found initrd image: /boot/initramfs-0-rescue-0ffe1c969db740f3bf50f4567ee5fba5.img
done
~]# grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1127.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1127.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-2b736cc499234bc4953ba55d0dd9288c
Found initrd image: /boot/initramfs-0-rescue-2b736cc499234bc4953ba55d0dd9288c.img
## 重启系统,确认生效
~]# dmesg | grep -i numa
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet[ 0.000000] NUMA turned off[ 0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-3.10.0-327.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto numa=off rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet
linux服务器linux系统numa
转载于 关于 NUMA 绑核,你需要了解的。。。 - 墨天轮