numa 架構下mysql可能遭遇的swap問題

myownstars發表於2013-05-03

相對於SMP(又稱uniform. memory architecture),NUMA引入了node的概念,每個物理CPU都被視作一個node,而每個node都有一個local memory(訪問速度更快),其他node的記憶體則為remote;

NUMA相關的策略
1、每個程式(或執行緒)都會從父程式繼承NUMA策略,並分配有一個優先node。如果NUMA策略允許的話,程式可以呼叫其他node上的資源。
2、NUMA的CPU分配策略有cpunodebind、physcpubind。cpunodebind規定程式執行在某幾個node之上,而physcpubind可以更加精細地規定執行在哪些核上。
3、NUMA的記憶體分配策略有localalloc、preferred、membind、interleave。localalloc規定程式從當前node上請求分配記憶體;而preferred比較寬鬆地指定了一個推薦的node來獲取記憶體,如果被推薦的node上沒有足夠記憶體,程式可以嘗試別的node。membind可以指定若干個node,程式只能從這些指定的node上請求分配記憶體。interleave規定程式從指定的若干個node上以Round-roll演算法交織地請求分配記憶體。

在現有的Redhat Linux中,localalloc是預設的NUMA記憶體分配策略,這個配置選項導致資源獨佔程式很容易將某個node的記憶體用盡。而當某個node的記憶體耗盡時,Linux又剛好將這個node分配給了某個需要消耗大量記憶體的程式(或執行緒),此時即便其他node有空閒記憶體也無濟於事,於是就產生了swap


可透過numactl檢視相關資訊
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會阻塞相應程式,因此不宜頻繁呼叫 
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已經使用了30多G,所剩無幾;
如果繼續在node 0請求記憶體,則需swap,即便此時node 1還有10G空餘;
解決方法:
使用interleave,輪詢各個node分配記憶體
修改mysqld_safe,在cmd="$NOHUP_NICENESS"後新增如下資訊
cmd="/usr/bin/numactl --interleave all $cmd"
此時NUMA記憶體分配情況
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生產庫144G記憶體,innodb buffer pool佔用120G;
除了採用numactl --interleave=all
在啟動mysqld前呼叫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位實現;

參考資料
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/ 
 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15480802/viewspace-759650/,如需轉載,請註明出處,否則將追究法律責任。

相關文章