1. 需求描述
觀察MongoDB的啟動Log,會看到一個關於 NUMA 的警告 和 優化建議
2018-07-17T17:00:04.516+0800 I CONTROL [initandlisten] ** WARNING: You are running on a NUMA machine. 2018-07-17T17:00:04.516+0800 I CONTROL [initandlisten] ** We suggest launching mongod like this to avoid performance problems: 2018-07-17T17:00:04.516+0800 I CONTROL [initandlisten] ** numactl --interleave=all mongod [other options] 2019-08-17T17:00:04.516+0800 I CONTROL [initandlisten]
那麼我們是不是要調整下Linux的系統配置?首先我們先補充下基本知識。
2.相關知識介紹
2.1 NUMA和SMP
NUMA和SMP是兩種CPU相關的硬體架構。
SMP (對稱多處理器結構: Symmetric Multi-Processor)
在SMP架構裡面,所有的CPU爭用一個匯流排來訪問所有記憶體,優點是資源共享,而缺點是當處理器的數目增大時,系統匯流排的競爭衝突加大,系統匯流排將成為瓶頸。隨著PC伺服器上的CPU數量變多(不僅僅是CPU核數),匯流排爭用的弊端慢慢越來越明顯。
NUMA ( 非一致儲存訪問結構: Non-Uniform Memory Access)
NUMA是指多處理器系統中,記憶體的訪問時間是依賴於處理器和記憶體之間的相對位置的。這種設計裡存在和處理器相對近的記憶體,通常被稱作本地記憶體;還有和處理器相對遠的記憶體,通常被稱為非本地記憶體。NUMA最大的特點是引入了node和distance的概念。對於CPU和記憶體這兩種最寶貴的硬體資源,NUMA用近乎嚴格的方式劃分了所屬的資源組(node),而每個資源組內的CPU和記憶體是幾乎相等。資源組的數量取決於物理CPU的個數(現有的PC server大多數有兩個物理CPU);distance是用來定義各個node之間呼叫資源的開銷,為資源排程優化演算法提供資料支援。
2.2 NUMA的利與弊
現在的機器上都是有多個CPU和多個記憶體塊的。以前我們都是將記憶體塊看成是一大塊記憶體,所有CPU到這個共享記憶體的訪問訊息是一樣的,這就是之前普遍使用的SMP模型。但是隨著處理器的增加,共享記憶體可能會導致記憶體訪問衝突越來越厲害,且如果記憶體訪問達到瓶頸的時候,效能就不能隨之增加。NUMA(Non-Uniform Memory Access)就是在這樣的背景下引入的一個模型。比如一臺機器是有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的本地記憶體中分配,會導致CPU節點之間記憶體分配不均衡,當某個CPU節點的記憶體不足時,會導致swap產生,而不是從遠端節點申請記憶體,即所謂的swap insanity 現象。現有的Redhat Linux中,localalloc策略是預設的NUMA記憶體分配策略(localalloc規定程式從當前node上請求分配記憶體,此外還有策略 preferred、membind、interleave),這個配置選項導致資源獨佔程式很容易將某個node的記憶體用盡。而當某個node的記憶體耗盡時,Linux又剛好將這個node分配給了某個需要消耗大量記憶體的程式(或執行緒),swap產生了。儘管此時還有很多page cache可以釋放,甚至還有很多的free記憶體。SWAP的罪與罰文章就說到了一個numa的陷阱的問題。現象是伺服器還有記憶體的時候,發現它已經在開始使用swap了,甚至導致機器出現停滯的現象。所以,如果限制一個程式只能使用自己的numa節點的記憶體,那麼當它自身numa node記憶體使用光之後,就不會去使用其他numa node的記憶體了,會開始使用swap,甚至更糟的情況,機器沒有設定swap的時候,可能會直接當機!
2.3 NUMA 與 Swap 的案例說明
例如,我們通過 numactl --hardware 來 檢視系統上的NUMA節點資訊,如下:
從上面的資訊可以 node 0 的 free 記憶體為312 MB,node 1 的free 記憶體為15254 MB。
可知,兩個Node 節點的 上的剩餘記憶體嚴重不均衡。
當Node 0 上需要申請大於312MB的記憶體時,就會產生SWAP。
即,由於伺服器硬體、系統設定不當,沒有關閉NUMA,容易導致發生SWAP。
檢視此伺服器的記憶體情況,確實如此。
總結; 如果你的程式是會佔用大規模記憶體的,應該考慮選擇關閉numa node的限制(或從硬體關閉numa),因為這個時候很有可能會碰到numa陷阱。另外,如果你的程式並不佔用大記憶體,而是要求更快的程式執行時間,可以考慮選擇限制只訪問本numa node的方法來進行處理。
3.numa 相關操作命令
1 安裝管理工具
yum install numactl -y
2.檢視系統的NUMA節點
numactl --hardware
3.檢視繫結資訊
numactl --show
4.檢視執行統計資訊
numastat
當 numa_miss數值比較高時,說明需要對分配策略進行調整,從而提高記憶體命中率。
4.CentOS7.x 關閉 NUMA
Step 1 編輯 /etc/default/grub 檔案,在GRUB_CMDLINE_LINUX 行上新增加:numa=off,如下圖:
Step 2 重新生成 /etc/grub2.cfg 配置檔案-----【此操作應慎重】
grub2-mkconfig -o /etc/grub2.cfg
Step 3 重啟作業系統
reboot
Step 4 修改驗證
dmesg | grep -i numa
或者
cat /proc/cmdline
顯示結果,出現了 numa=off 字元
在此設定下,重新MongoDB服務,檢視log記錄,關於NUMA的警告資訊不再出現。
參考資料:
1.https://www.thegeekdiary.com/how-to-disable-numa-in-centos-rhel-67/;
2.https://www.jianshu.com/p/e36c54b4b53e
3.部分資料梳理於網路分享。