Varidata 新聞資訊
知識庫 | 問答 | 最新技術 | IDC 行業新聞
Varidata 知識文檔

限制記憶體超分以防止 OOM

發布日期:2026-10-27
展示 Linux 記憶體超分限制與伺服器 OOM 控制機制的示意圖

在真實的基礎設施環境中,記憶體超分並不天然等同於錯誤,它首先是一種策略選擇。真正的問題出現在虛擬分配、容器限制、來賓系統預期以及業務峰值行為,逐漸偏離實體資源現實的時候。到了這個階段,核心就不會再「客氣」,而是開始激進回收記憶體、阻塞任務,或者直接觸發 OOM killer。對於運行在香港伺服器上的業務,尤其是對延遲敏感的服務來說,健康的超分與魯莽的過度分配之間,往往就是一次短暫波動與一次生產事故之間的區別。

核心問題並不複雜:很多系統在「帳面上」預留的記憶體,已經超過了它們在同一時刻能夠安全承載的範圍。對於突發型應用、且同時高壓機率較低的場景,這種方式有時可以成立;但一旦多個行程同時增長、檔案快取與使用者態記憶體爭搶,或者 swap 變成一條低速應急通道,系統就會迅速失穩。根據 Linux 核心文件,超分行為受 vm.overcommit_memory、vm.overcommit_ratio 與 vm.overcommit_kbytes 等參數控制,而 OOM 處理也可以透過 cgroup 記憶體控制和行程評分機制進行塑形。

記憶體超分到底意味著什麼

記憶體超分指的是:作業系統允許行程申請的虛擬記憶體總量,超過目前實體 RAM 與 swap 所能立即支撐的水準。這種機制之所以普遍存在,是因為並不是每一頁已分配記憶體都會被真正存取,而且很多應用會預留位址空間,卻不會全部實際使用。Linux 支援多種超分模式:一種是啟發式模式,一種是較寬鬆的模式,假定在真正耗盡之前記憶體總能「想辦法騰出來」,還有一種則更嚴格,目的是在系統走到懸崖邊之前,就提前阻止過度承諾。

對維運和架構人員來說,這個差異非常關鍵。一台機器在低流量階段看起來也許完全正常,因為很多分配還停留在「理論層面」。但當批次處理任務啟動、快取預熱、流量暴增,或者並發數上升時,那些之前只是被「預留」的記憶體,就會變成真正的常駐記憶體。機器之所以出問題,並不是因為監控面板曾經顯示還有空閒 RAM,而是因為過多「承諾」在同一時刻集中兌現。

  • 虛擬記憶體預留並不等於活躍記憶體消耗。
  • 啟發式超分可以提升利用率,但絕不是安全保證。
  • 嚴格記帳能降低風險,但也會更早拒絕部分分配請求。
  • 容器和來賓系統的限制,可能會掩蓋壓力,直到宿主機已經不堪重負。

為什麼激進分配之後會出現 OOM 風暴

反覆出現的 OOM,通常並不是由某一個戲劇性的單點原因引發的。更常見的情況是,多層假設疊加在一起:某個服務為「以防萬一」而慷慨預留記憶體,排程器又把過多副本放在同一節點上,swap 雖然存在,但在高壓下回收延遲急劇放大。與此同時,宿主機還被期待繼續承擔檔案快取、核心開銷,以及突發流量帶來的增長。當足夠多的元件都按照「平均情況」而不是「最壞重疊場景」來調校時,OOM 幾乎只是時間問題。

Linux 文件說明,在寬鬆超分模式下,核心實際上預設「記憶體未來大機率會有」,直到事實證明並沒有。而在嚴格模式下,記憶體承諾會被限制在 RAM、swap 和提交策略允許的範圍內。這也解釋了為什麼同一套工作負載,在一種設定下看起來穩定,在另一種設定下卻會迅速失敗。很多時候,快速失敗反而比在資源爭用下隨機死亡更容易排查。

  1. 並發峰值重疊:多個服務不是輪流上升,而是在同一時間一起擴張。
  2. 宿主機隱藏開銷:頁面快取、核心記憶體和配置器碎片會吃掉很多規劃模型容易忽略的空間。
  3. 租戶隔離不足:一個高噪音工作負載會把另一個服務推進回收甚至 OOM。
  4. 發現太晚:告警只盯平均 RAM,不看提交量增長、回收壓力或 cgroup 壓力。

如何確認真正的根因就是超分

在調整策略之前,先確認故障模式。系統崩潰也可能源於真實的記憶體洩漏、意外的行程風暴、失控的快取設定,或者宿主層之上的過度超賣。排查時首先要看核心日誌,因為 OOM 事件通常會在那裡留下清晰痕跡。核心在處理 OOM 時可能輸出任務資訊,而每個行程的評分機制,也能幫助解釋為什麼死掉的是這個任務,而不是另一個。

接著,不要只盯「已使用記憶體」,而要檢查「提交量」。Linux 會在 /proc/meminfo 中暴露 Committed_AS 和 CommitLimit,這有助於區分普通記憶體壓力與結構性的過度超分。如果已提交位址空間持續逼近甚至超過實際可承受上限,而 RSS 還沒有顯著增長,那麼更大的問題往往不在瞬時使用量,而在於策略本身過於樂觀。

  • 檢查核心日誌,確認被殺行程與 OOM 上下文。
  • 對比活躍使用量與已提交位址空間。
  • 判斷是 cgroup 記憶體越界,還是宿主機整體耗盡。
  • 觀察 swap 使用、回收延遲與快取壓力。

如何限制過度分配而又不至於廢掉利用率

最聰明的做法,不是到處一刀切地禁止超分,而是劃清邊界:哪些場景可以適度樂觀,哪些場景一旦樂觀就很危險。無狀態邊緣行程通常比吃記憶體的有狀態服務更適合高密度部署;批次處理任務往往允許失敗後重試,而交易型後端則通常不具備這種容錯空間。穩定營運依賴的是邊界,而不是僥倖。

在核心層面,最直接的控制手段之一就是 vm.overcommit_memory。根據官方文件,0 表示啟發式模式,1 表示允許較寬鬆的超分,而 2 則表示更嚴格的近似「禁止過度超分」模式,其上限由 swap 加上額外允許值共同決定。這個允許值可以透過 vm.overcommit_ratio 或 vm.overcommit_kbytes 進行控制。

  1. 在宿主機層預留餘量。 給核心、快取、回收損耗以及短時突發保留空間,而不是把所有記憶體都分給來賓系統或服務。
  2. 關鍵節點採用更嚴格的策略。 當穩定性比部署密度更重要時,嚴格的提交規則可以減少「意外分配」。
  3. 敏感環境優先考慮絕對值限制。 在節點規格差異較大時,overcommit_kbytes 往往比比例參數更容易推導和管理。
  4. 按工作負載類型做分池。 不要指望波動型服務和穩定型服務總能和平共處。

這並不意味著每一台伺服器都應該使用最嚴格的設定,而是意味著你的承諾模型必須與業務可接受的失敗方式相匹配。用於多租戶伺服器租用的基礎設施,通常比單一用途的內部節點更需要強約束;而面向伺服器託管的環境,也往往需要更清晰的記憶體契約,因為相鄰工作負載的演化路徑通常並不同步。

用 cgroup 和硬上限控制爆炸半徑

如果說宿主機策略是城牆,那麼 cgroup 就是每一戶的防火門。Linux cgroup 文件明確說明,當某個 memory cgroup 到達其限制,而回收又無法釋放足夠空間時,OOM 處理就可能在該 cgroup 內部發生。這樣一來,維運團隊就可以避免單個服務把整台機器一起拖下水。

對技術團隊來說,這是最實用的控制手段之一。為每個服務組設定合理的記憶體上限,並根據真實執行行為校準,不要犯「每個行程都先給一個慷慨上限以防萬一」的常見錯誤。如果每個單元都被允許成為例外,最終倒楣的只會是宿主機。

  • 為每個服務組定義記憶體上限。
  • 將關鍵路徑與背景任務分開隔離。
  • 在硬失敗之前設定更柔和的預警閾值。
  • 調整 OOM 評分,讓低價值任務比核心行程更「適合被犧牲」。

Swap 是緩衝,不是救命方案

維運人員常常會問:增加 swap 能不能解決 OOM?答案是,它有幫助,但幫助有限。核心文件表明,在嚴格記帳模式下,提交策略本身就會將可用 swap 納入考量,因此 swap 的確能增加一定緩衝空間。但問題在於,用磁碟型記憶體替代 RAM,會改變故障形態:你可能不再立刻被殺行程,卻會遇到長時間阻塞、回收抖動和服務逾時。

更務實的理解是:swap 適合吸收短暫尖峰,給自動化恢復爭取時間;但如果工作負載長期配置不足,或者某個服務本身存在病態增長,swap 就幫不上太多。一個主要依靠頻繁交換才能「活著」的伺服器,通常已經處於不健康狀態。

應用行為往往比策略本身更關鍵

很多記憶體超分問題最後被歸咎於平台,但真正寫下結局的,往往還是應用本身。執行緒數、工作行程池、快取策略、佇列消費者、執行階段特性以及配置器習慣,都會決定節點能否保持可預測性。如果某個服務擴並發的速度,比系統回收記憶體的速度還快,那麼再漂亮的 sysctl 也撐不了多久。

因此,調校應該分層進行:

  1. 減少不必要的並發。
  2. 限制工作行程數量與佇列深度。
  3. 快取大小要合理,不要為了好看的命中率而無限膨脹。
  4. 在演變成分頁風暴之前,盡早發現洩漏與增長漂移。
  5. 讓服務級限制與宿主策略保持一致,避免一層設定抵銷另一層約束。

更偏極客的團隊,往往會從把提交量增長、重大缺頁、回收活動以及 cgroup 壓力放到同一張圖上開始獲益。因為一條平穩的平均記憶體曲線,完全可能掩蓋一台只差一次發布就會崩潰的節點。

面向香港伺服器部署的實戰建議

香港伺服器常常承載區域閘道、交易鏈路、內容分發邊緣、遊戲架構以及跨境 Web 平台,這類場景裡,延遲與穩定性通常比把部署密度壓榨到極致更重要。在這樣的環境中,保守的記憶體規劃往往是更合理的取捨。一次 OOM 事件影響的並不只是某個行程,它還可能打斷工作階段連續性、觸發級聯重試,並在周邊系統中放大故障噪音。

一個更穩妥的執行模型通常包括:

  • 在宿主機層為流量突發和快取波動預留餘量。
  • 在關鍵節點上使用更嚴格的提交策略。
  • 透過 cgroup 上限隔離不同工作負載。
  • 把 swap 當作臨時減震層,而不是實際容量。
  • 每次出現 OOM 事件後都回看日誌,而不是把它當成「偶發現象」忽略掉。

結語

減少 OOM 頻率的最乾淨辦法,是停止把記憶體當成一種「可以隨便樂觀假設」的資源。該超分的地方可以超分,但必須基於工程判斷,而不是出於帳面利用率的誘惑。Linux 核心已經提供了足夠多的旋鈕:提交策略、提交上限、cgroup 隔離,以及 OOM 評分。真正關鍵的是,如何把這些機制組合成一個符合工作負載真實爭用行為的模型,而不是只符合某個風平浪靜時刻的監控截圖。對於運行在香港伺服器上的穩定業務來說,記憶體超分應該是經過刻意設計、可度量、並且被明確邊界所約束的,而不是一種最終以災難方式失敗的「預設僥倖」。

您的免費試用從這裡開始!
聯繫我們的團隊申請實體主機服務!
註冊成為會員,尊享專屬禮遇!
您的免費試用從這裡開始!
聯繫我們的團隊申請實體主機服務!
註冊成為會員,尊享專屬禮遇!
Telegram Teams