Linux 內核 101:NUMA架構

本文參考瞭如下文章、視頻:node

一句話

NUMA 指的是針對某個 CPU,內存訪問的距離和時間是不同的。是爲了解決多 CPU 系統下共享 BUS 帶來的性能問題。(這句話可能不太嚴謹,不是爲了解決,而是事實上解決了。)mysql

NUMA 架構圖

從最簡單的開始,一個 CPU(注意:這裏指的是物理 CPU,不是核。須要注意的一點是NUMA 是針對多物理 CPU 而言的,而不是多核。),經過 bus 和 RAM 相連。git

接下來多CPU 出現了(再說一次,不是多核單CPU!),若是仍是像以前那樣將全部的CPU 經過一個 BUS 和 RAM 相連,BUS 會成爲性能的殺手。並且,加的 CPU 越多,性能損耗會越高。github

這時候 NUMA 架構就展露身手了:經過把 CPU 和臨近的 RAM 當作一個 node,CPU 會優先訪問距離近的 RAM。同時,CPU 直接有一個快速通道鏈接,因此 每一個CPU 仍是訪問到全部的 RAM 位置(只是速度會有差別)。算法

實際中,一個不必定單獨佔有一個 RAM,能夠有下面這些不少種組合:sql

淺看 Linux 中的NUMA架構

如下操做在阿里云云服務器 Ubuntu18.04環境下運行數據庫

首先經過dmesg | grep -i numa查看一下系統是否是支持numa:可見當前系統不支持 :)bash

而後使用一個工具:numactl,能夠經過 apt install numactl進行安裝。而後運行:服務器

numactl --hardware
複製代碼

還有一個實用工具:lstopo,經過 apt install lstopo微信

lstopo --of png > server.png
複製代碼

從圖中能夠看到,有一個node 節點。爲何個人系統不支持 numa,Linux 仍是把全部的 CPU 和全部的 RAM 組合到一塊兒成爲一個 node 呢?這不是閒的沒事幹嘛?

關於這一點,《Understanding the Linux Kernel》一書裏面這麼說:

這主要是出於代碼可擴展性的考慮,這樣一套代碼就能夠在不支持 numa 和支持 numa 的環境下運行了。

若是是支持 numa 架構的服務器,看到的圖會是這樣的:

NUMA 對Linux 會產生什麼影響?

系統 boot 的時候,硬件會把 numa 信息發送給 os,若是系統支持 numa,會發生如下幾件事:

  • 獲取 numa 配置信息
  • 將 processors(不是 cores) 分紅不少 nodes,通常是一個 processor 一個 node。
  • 將 processor 附近的 memory 分配給它。
  • 計算node 間通訊的cost(距離)。

若是你只是把 CPU 和內存看成是黑盒子,簡單地期待它 work 的話,可能會發生意想不到的事情。

  • 每一個進程、線程都會繼承一個 numa policy,定義了可使用那些CPU(甚至是那些 core),哪些內存可使用,以及 policy 的強制程度,便是優先仍是強制性只容許。
  • 每一個 thread 被分配到了一個」優先」 的 node 上面運行,thread 能夠在其餘地方運行(若是 policy 容許的話),可是 os 會嘗試讓他在優先地 node 上面去運行。
  • 內存分配:默認內存從同一個 node 裏面進行分配。
  • 在一個 node 上面分配地內存不會被移動到其餘node。

上面兩段翻譯自: blog.jcole.us/2010/09/28/… ,若有不清晰的地方,請移步原文。

看一個MySQL 的實例

優質好文,有能力的同窗最好仍是直接看原文: blog.jcole.us/2010/09/28/… 我這裏簡單翻譯一下。

文中提到了一個問題:在一個有64G 內存、2個 4核 CPU 的 Linux 服務器中運行 MySQL 服務,MySQL 配置了48G 的 innodb buffer pool。而後發現,儘管系統還有不少空餘的內容,不少內存被 swap 出去了。

這帶來了極大的性能問題,由於query 的時候若是須要的內容被 swap 出去了。。就須要再 load 回來。這也是困惱了MySQL 社區很長時間的問題。

前面說到 Linux 有一個 numa policy,這個是能夠人爲控制的。

  • —localalloc ,使用當前 node,默認。
  • --preferred=node,優先實用指定的 node,實在不行用其餘的 nod 也能夠。
  • --membind=nodes,老是使用人爲指定一個或多個 nodes。
  • --interleaved=all,採用round-robin算法輪流使用不一樣的 node。

從 Linux os 的角度來看,MySQL 數據庫就是一個進程,會優先讓他在某一個 node 中運行。若是隻是使用少部份內存,這沒什麼問題,可是當你要佔用系統大多數內存的時候,問題就來了:

因爲 os 會試圖讓你在某個『優先』的node裏面運行,就會產生內存分配不均勻的狀況:

Node0 已經快被佔滿了,Node1還剩下不少。因爲 node0和 node1是獨立的,儘管 node1裏面有空餘內存,node0裏面的內存仍是會被 swap 出去。這就是前面提到的問題的根源。

那麼怎麼解決呢?

numactl --interleave all command
複製代碼

用前面提到的--interleave all numa policy,將這段添加到mysqld_save 語句前面。事後,內存分配就是均勻的了,內存足夠的狀況下,就不會出現異常的 swap 現象了。

固然這只是一個最簡單粗暴的解決方案,還有其餘更好的,原文有說起,可是不是本文的重點,因此就不深刻探討了。

總結一下

摩爾定律正在失效,當 CPU 的性能總會有極限的那一天,多 CPU 纔是將來。做爲一個有理想的搬磚工人,至少仍是應該多瞭解一下多 CPU 系統架構。做爲一個系統軟件開發者,更應該熟悉多 CPU 架構,讓本身開發的應用充分利用硬件福利。

廣告時間,歡迎你們關注個人微信公衆號。同時本文同步於 github: github.com/liaochangji…

相關文章
相關標籤/搜索