现代主机,尤其是多核系统,已经成为标准配置了,
什么事NUMA ?
Non Uniform Memory Access 非一致性内存访问架构 。
现在的X86-64系统架构都是这样的了。
就是内存跟cpu 有一个绑定。比如我们的系统 64g内存 2*8cpu
那么 就是 两个cpu 每个分的32g 内存
cpu 1 上的进程、线程,优先使用本地的32g 内存,如果要访问 cup2 上的内存,就会花很大的力气。
性能会下降。
这里就引入了一个问题:
比如我们的oracle 系统,如果在linux 架构上,分配的内存大于32G
就可能带来内存访问方面的问题。
PG ,mysql 也有这个问题。
numa 的内存访问策略,默认的是local ,也就是优先使用本地内存, 这里就存在一个问题,
数 据库 pg oracle 是多进程的,如果分配的sga 接近或者超过32g ,新的进程在同一个物理cpu 启动的时候,发现内存不够了,就有可能会导致swap ,而实际上,另一个物理cpu 的内存还没有用完,还可以在另一个物理cpu上绑定的内存上,继续分配内存。
假设,我们启动数据库,sga 分配在cpu 1上绑定的内存,而某一个连接,是在cup2 上运行,
那么这个进程访问sga 的时候,性能就会比在cpu 1 上运行的进程低很多,同样的在cpu1上运行的进程,可能更容易发生swapness 。
我们目前的问题:
我们的mysql 目前是采用的单机多实例的方式运行,每个数据库实例配置的内存都不是很大,基本不会发生这个问题。
oracle 与 pg 数据库 ,则可能存在我们上面提到的问题。
怎么避免呢? 单机单实例的数据库,建议关闭numa 策略。
主机OS层面 提供了一些工具来帮助我们实施。
一个是numastat 一个是numactl
看看先:
numastat 就是打印系统目前的numa情况:
[root@pgsql-238-181 ~]# numastat
node0 node1
numa_hit 7215446485 7503909011
numa_miss 850409592 149660507
numa_foreign 149660507 850409592
interleave_hit 13764 13784
local_node 7215347684 7503856800
other_node 850508393 149712718
各个字段的含义 看 man page 吧。
numactl 可以用来改变系统的策略
默认是default ,
[root@pgsql-238-181 ~]# numactl --show
policy: default ## numa策略 默认
preferred node: current ## 内存分配方式,在当前节点上分配
physcpubind: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ## cpu 编号
cpubind: 0 1 ## 物理cpu ,我们的是两个cpu 所以为0 1
nodebind: 0 1 ## 节点绑定, 两个物理cpu 分为连个节点
membind: 0 1 ## 内存绑定, 两个对应到前面的nodebind
[root@pgsql-238-181 ~]#
[root@pgsql-238-181 ~]# numactl --hardware
available: 2 nodes (0-1) ## 可用节点
node 0 cpus: 0 1 2 3 8 9 10 11 ## node 0 上cpu
node 0 size: 16372 MB ## node 0 上分配的内存大小 16g
node 0 free: 475 MB ## node 0 上空闲内存 475m
node 1 cpus: 4 5 6 7 12 13 14 15 ## 下面是node 1 的情况,同上
node 1 size: 16384 MB
node 1 free: 1188 MB
node distances: ## node 间 的距离,这个一个度量值,没有实际意义。
node 0 1
0: 10 21 ## 这个矩形 说明的是 ,node 0 的上cpu 访问node 0 上分配的内存,需要的权重,
1: 21 10 ## 或者距离 是10 , 如果访问node 1 上的分配的内存的权重或者距离是21 ,
## node 1 上的cpu 也一样, 访问本地,是10 访问对方是21
从上面可见,访问异地的内存,开销是访问本地的两倍多。
numactl 的更多细节 查看 man page
针对我们的数据库主机,我们应该采用什么策略呢?
针对我们上面的提出的问题,我们建议采用 interleave 模式。 即 交叉分配,这样基本可以做到内存平均的分配到两个node 里,
每个进程, 访问本地与访问异地内存的比例是1:1 。
基本可以可以避免我们前面说到的,系统有大量内存的时候,还发生swap 。
怎么用呢, 进程一旦启动就不会再受到numa策略的影响了,所以应该在启动进程的时候,指定 numa 策略。
需要修改 启动脚本。
增加 /usr/bin/numactl --interleave all $CMD
例如PG数据库 numactl --interleave all pg_ctl start
我们看看进程的分部情况:
more /proc/26929/numa_maps
00400000 interleave:0-1 file=/data/postgresql-9.1.4/bin/postgres mapped=217 mapmax=6 active=199 N0=189 N1=28
00ad9000 interleave:0-1 file=/data/postgresql-9.1.4/bin/postgres anon=12 dirty=12 mapmax=6 N0=6 N1=6
00ae5000 interleave:0-1 anon=15 dirty=15 mapmax=6 N0=8 N1=7
02a50000 interleave:0-1 heap anon=50 dirty=50 mapmax=6 N0=26 N1=24
34bda00000 interleave:0-1 file=/lib64/ld-2.12.so mapped=28 mapmax=49 N0=28
34bdc1f000 interleave:0-1 file=/lib64/ld-2.12.so anon=1 dirty=1 mapmax=6 N1=1
34bdc20000 interleave:0-1 file=/lib64/ld-2.12.so anon=1 dirty=1 N0=1
34bdc21000 interleave:0-1 anon=1 dirty=1 mapmax=4 N1=1
接下来的事情,就是安排修改主机的启动脚本了。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/133735/viewspace-751095/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/133735/viewspace-751095/