MongoDB 啟動時關於 NUMA 警告 的分析----(To avoid performance problems)

東山絮柳仔發表於2019-07-23

 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之間呼叫資源的開銷,為資源排程優化演算法提供資料支援。

NUMA系統的結點通常是由一組CPU(如,SGI Altix 3000是2個Itanium2 CPU)和本地記憶體組成,有的結點可能還有I/O子系統。由於每個結點都有自己的本地記憶體,因此全系統的記憶體在物理上是分佈的,每個結點訪問本地記憶體和訪問其它結點的遠地記憶體的延遲是不同的,為了減少非一致性訪存對系統的影響,在硬體設計時應儘量降低遠地記憶體訪存延遲(如通過Cache一致性設計等),而作業系統也必須能感知硬體的拓撲結構,優化系統的訪存。

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.部分資料梳理於網路分享。

相關文章