1. 需求描述 觀察MongoDB的啟動Log,會看到一個關於 NUMA 的警告 和 優化建議 那麼我們是不是要調整下Linux的系統配置?首先我們先補充下基本知識。 2.相關知識介紹 2.1 NUMA和SMP NUMA和SMP是兩種CPU相關的硬體架構。 SMP (對稱多處理器結構: Symmet ...
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的警告信息不再出現。
5.設置 interleave=all
在上面的操作中,其實我們並沒有針對 interleave=all 進行設置。針對這個建議,我們是不是還可以進行一些設置。
繼續進行測試,換一臺機器。
5.1 測試環境
修改配置前;
MongoDB log 的啟動記錄
2018-07-23T16:50:42.844+0800 I CONTROL [initandlisten] ** WARNING: You are running on a NUMA machine. 2018-07-23T16:50:42.844+0800 I CONTROL [initandlisten] ** We suggest launching mongod like this to avoid performance problems: 2018-07-23T16:50:42.844+0800 I CONTROL [initandlisten] ** numactl --interleave=all mongod [other options]
NUMA的信息;
從上面的信息可以看出NUMA是開啟的。
5.2 在BIOS層設置interleave
下麵的操作是在BIOS層,設置interleave。需通過遠程管理卡去調整。
Step 1:遠程管理開連接指定機器後,點擊【巨集】--》點擊【Ctl-Alt-Del】進行重啟 (特別註意:【Ctl-Alt-Del】 針對Windows系統是解除本機鎖定;Linux系統是要重啟,要特別小心)
Step 2 出現以下界面時,在鍵盤上請按下F2鍵,進行System Setup
Step 3 啟動後,選擇【System Bios】
Step 4 選擇 【Memory Settings】
Step 5 針對【Node Interleaving】選項 由【Disabled】調整為【Enabled】
調整前
調整後
Step 6 後退【即上一步點擊Back】後,點擊【Finish】,然後點擊【Yes】
Step 7 點擊 【OK】
Step 8 點擊Finish,點擊同意重啟
Step 9 重啟OK
5.3 修改效果驗證
查看NUMA信息,數據顯示NUMA已經關閉
重啟MongoDB實例,查看Log中沒有了NUMA的相關警告。
說明通過上面BIOS的調整,關閉了NUMA。
參考資料:
1.https://www.thegeekdiary.com/how-to-disable-numa-in-centos-rhel-67/;
2.https://www.jianshu.com/p/e36c54b4b53e;
3.https://blog.csdn.net/S100400507/article/details/45245663;
4.部分資料梳理於網路分享。