NUMA

Posted by danner on June 13, 2019

非统一内存访问架构Non-uniform memory access,简称 NUMA)是一种为多处理器的电脑设计的内存架构,内存访问时间取决于内存相对于处理器的位置 。举个简单的例子: 比如一台机器是有 2 个处理器,有4个内存块。我们将1个处理器和两个内存块合起来,称为一个 NUMA node,这样这个机器就会有两个 NUMA node。在物理分布上,NUMA node 内的处理器和内存块的物理距离更小,因此访问也更快。比如这台机器会分左右两个处理器(cpu1, cpu2),在每个处理器两边放两个内存块(memory1.1, memory1.2, memory2.1,memory2.2),这样 NUMA node1 的 cpu1 访问 memory1.1 和 memory1.2 就比访问 memory2.1 和 memory2.2 更快。

使用 NUMA 的模式如果能尽量保证本 node 内的 CPU 只访问 node 内的内存块,那这样的效率就是最高的。

NUMA 架构导致 cpu 访问不同的内存速度会有快慢。很容易就想到启用 numa node 限制(只使用NUMA node 里的内存),但这里会有一个问题:当 node 的内存用完后,开始使用 SWAP,显然此时处理速度会减慢(swap 磁盘交换,一直swap 会负载攀升,最终导致宕机 ),若机器没有设置 swap 会直接死机;简而言之 node 限制导致空闲其他node 内存和负载飙升,具体参考 SWAP的罪与罚

在实际生产中应该如何设置 NUMA

  • 如果程序占用大量内存,你可以关闭 numa node 的限制
  • 如果程序 只占用少量内存且追求处理速度,你可以开启 numa node 限制,但有可能发生上面提及的问题

NUMA 涉及到内存使用,那么在实际生产中是很容易出问题,一起来看看几个案例

MySQL

机器有大量空闲内存却发生 swap,有时 OOM

vmstat 命令实时查看 内存使用情况

# 每隔 1 s
[hadoop@danner000 ~]$ vmstat 1     
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 381004 196680 1972148  10   12     23   24    8   37  0  0 100  0  0
 0  0      0 380988 196680 1972148  11   15     20   90  142  229  0  1 99  0  0

可以看到 swap 一直发生(si、so 一般都为0),接下来看看内存的使用情况。

[hadoop@danner000 ~]$ free -gt
             total       used       free     shared    buffers     cached
Mem:          256         200        56          0       20          180

内存是空闲很多的,但为何会频繁发生 swap 呢?用 numa 看看

[hadoop@danner000 ~]$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3
node 0 size: 131037 MB
node 0 free: 1851 MB
node 1 cpus: 4 5 6 7
node 1 size: 131071 MB
node 1 free: 38670 MB
node distances:
# 下面cpu 访问内存距离
node   0   1 
  0:  10  20 
  1:  20  10 

可以看到内存使用严重不均衡(38 vs 1.8),如果此时再向node 0申请大内存就发生 swap。显然是由于开启 NUMA 限制引起的,该如何解决:

  • BIOS 层关闭 NUMA,需重启

  • 升级 MySQL 版本到 5.6.27 及以后,新增了一个选项 innodb_numa_interleave,只需要重启 mysqld 实例,无需重启OS,推荐此方案
  • MySQL 版本在 5.6.27 之前,带参数启动 ` numactl –interleave=all mysqld_safe &interleave` 会均匀是用内存,详细看参考资料一

SWAP

内核参数 vm.swappiness 可以设置多大概率使用 swap 。有两种方式可以修改

  • 当前立即生效:

    [hadoop@danner000 ~]$ cat /proc/sys/vm/swappiness 
    60
    [hadoop@danner000 ~]$ sysctl vm.swappiness=10
    
  • 重启永久生效

    [hadoop@danner000 ~]$ echo "vm.swappiness = 10" >> /etc/sysctl.conf
    [hadoop@danner000 ~]$ sysctl -p
    

该参数可选范围从 0 - 100,设为 0 就是希望最大限度使用物理内存,尽量不使用swap,设为 100 则是希望积极使用swap。在运行数据库进程的服务器上,我们通常强烈建议这个值小于等于10,最好是设置为 0。原因很简单,对数据库这种需要集中CPU资源、大内存、高I/O的程序而言,如果用SWAP分区代替内存,那数据库服务性能将是不可接受的,还不如直接被 OOM kill

参考资料

NUMA架构的CPU – 你真的用好了么?

NUMA的取舍

NUMA 命令

找到MySQL服务器发生SWAP罪魁祸首

微博某业务数据库连续两次 oom 问题分析

mysql5.7.9+支持的新参数innodb_numa_interleave