numa 架構(gòu)下mysql可能遭遇的swap問題
相對于SMP(又稱uniform. memory architecture),NUMA引入了node的概念,每個物理CPU都被視作一個node,而每個node都有一個local memory(訪問速度更快),其他node的內(nèi)存則為remote;
NUMA相關(guān)的策略
1、每個進程(或線程)都會從父進程繼承NUMA策略,并分配有一個優(yōu)先node。如果NUMA策略允許的話,進程可以調(diào)用其他node上的資源。
2、NUMA的CPU分配策略有cpunodebind、physcpubind。cpunodebind規(guī)定進程運行在某幾個node之上,而physcpubind可以更加精細地規(guī)定運行在哪些核上。
3、NUMA的內(nèi)存分配策略有l(wèi)ocalalloc、preferred、membind、interleave。localalloc規(guī)定進程從當前node上請求分配內(nèi)存;而preferred比較寬松地指定了一個推薦的node來獲取內(nèi)存,如果被推薦的node上沒有足夠內(nèi)存,進程可以嘗試別的node。membind可以指定若干個node,進程只能從這些指定的node上請求分配內(nèi)存。interleave規(guī)定進程從指定的若干個node上以Round-roll算法交織地請求分配內(nèi)存。
在現(xiàn)有的Redhat Linux中,localalloc是默認的NUMA內(nèi)存分配策略,這個配置選項導致資源獨占程序很容易將某個node的內(nèi)存用盡。而當某個node的內(nèi)存耗盡時,Linux又剛好將這個node分配給了某個需要消耗大量內(nèi)存的進程(或線程),此時即便其他node有空閑內(nèi)存也無濟于事,于是就產(chǎn)生了swap
可通過numactl查看相關(guān)信息
numactl --hardware查看
# numactl --hardware
available: 2 nodes (0-1)
node 0 size: 32276 MB
node 0 free: 26856 MB
node 1 size: 32320 MB
node 1 free: 26897 MB
node distances:
node 0 1
0: 10 21
1: 21 10
通過/proc/pid/numa-maps可以查看分配給mysqld的numa信息--讀取numa-maps會阻塞相應進程,因此不宜頻繁調(diào)用 2aaaaad3e000 default anon=13240527 dirty=13223315
swapcache=3440324 active=13202235 N0=7865429 N1=5375098
可通過perl腳本格式化輸出
N0 : 7983584 ( 30.45 GB)
N1 : 5440464 ( 20.75 GB)
active : 13406601 ( 51.14 GB)
anon : 13422697 ( 51.20 GB)
dirty : 13407242 ( 51.14 GB)
mapmax : 977 ( 0.00 GB)
mapped : 1377 ( 0.01 GB)
swapcache : 3619780 ( 13.81 GB)
Node 0/1各分配32G,但是 node 0已經(jīng)使用了30多G,所剩無幾;
如果繼續(xù)在node 0請求內(nèi)存,則需swap,即便此時node 1還有10G空余;
解決方法:
使用interleave,輪詢各個node分配內(nèi)存
修改mysqld_safe,在cmd="$NOHUP_NICENESS"后添加如下信息
cmd="/usr/bin/numactl --interleave all $cmd"
此時NUMA內(nèi)存分配情況
N0 : 6814756 ( 26.00 GB)
N1 : 6816444 ( 26.00 GB)
anon : 13629853 ( 51.99 GB)
dirty : 13629853 ( 51.99 GB)
mapmax : 296 ( 0.00 GB)
mapped : 1384 ( 0.01 GB)
twitter生產(chǎn)庫144G內(nèi)存,innodb buffer pool占用120G;
除了采用numactl --interleave=all
在啟動mysqld前調(diào)用sysctl -q -w vm.drop_caches=3清空緩存
并且啟動mysqld立即分配innodb buffer pool
注:也可在BIOS層面將NUMA改為SUMA,在底層將所有分配策略都設為interleave,但粒度太大不利于分化;
默認innodb buffer pool采用lazy-allocation,可采用--innodb-buffer-pool-populate立即分配,通過使用mmap的MAP_POPULATE位實現(xiàn);
參考資料
http://blog.wl0.org/2012/09/checking-procnuma_maps-can-be-dangerous-for-mysql-client-connections/
http://blog.jcole.us/2010/09/28/mysql-swap-insanity-and-the-numa-architecture/
http://www.realzyy.com/?p=1245#more-1245
http://kevinclosson.wordpress.com/2009/05/14/you-buy-a-numa-system-oracle-says-disable-numa-what-gives-part-ii/