Linux內存擴容從問題、原理、配置到踩坑修復的完整過程
我這臺機器 32G 內存、i7-10700,CPU 大多數(shù)時候閑著,但內存一吃緊就卡死。只用幾行配置,我把內存的一半劃給 zram 當壓縮 swap,把用不上的 CPU 換成更耐用的內存。配置時在 Ubuntu 22.04 上踩了一個坑:照網上的新語法寫,zram 只給了我 4G。這篇記錄從問題、原理、配置到踩坑修復的完整過程。
一、我的問題
我的機器是 Ubuntu 22.04.5、內核 6.8,31 GiB 內存(標稱 32G),CPU 是 i7-10700,16 個線程。平時開著瀏覽器、編輯器和幾個容器,內存一沖高就卡死,鼠標都拖不動,要等十幾秒才緩過來。但同一時間 CPU 基本是閑的。
先看了內存和 swap:
$ free -h
total used free shared buff/cache available
Mem: 31Gi 8.6Gi 11Gi 909Mi 10Gi 21Gi
Swap: 2.0Gi 0B 2.0Gi
$ swapon --show
NAME TYPE SIZE USED PRIO
/swapfile file 2G 0B -2
只有一個 2 G 的磁盤 swapfile 在兜底。內存一緊,內核就往這塊慢盤上倒頁,一旦開始來回換頁(thrashing),整機就卡住。swappiness 是默認的 60,沒有 zram,zswap 也沒開。
思路很直接:內存不夠、CPU 有余,那就用 CPU 換內存——上 zram。
二、zram 是什么,為什么能換
zram 在內存里建一塊塊設備,寫進去的數(shù)據(jù)先用壓縮算法壓一遍再存。把它當 swap 用,內核換出的頁就被壓縮后留在內存里,而不是寫到磁盤。匿名頁(進程的堆棧、數(shù)據(jù)這類沒有文件后備的內存)通常能壓到原大小的三分之一左右,于是同樣的物理內存能裝下更多內容。代價是每次換出、換入都要花 CPU 做壓縮和解壓,而這正是我富余的資源。

圖 1. zram 作為 swap 時一頁內存換出/換入的數(shù)據(jù)通路,全程在內存內完成。
幾個要點:
- zsmalloc:內核里專門的分配器,把大小不一的壓縮塊緊湊地打包進內存頁,減少碎片,讓壓縮省下的空間真正變成可用容量。
- 壓縮算法:可選
lz4(快、壓縮比一般)、zstd(壓縮比高、稍慢)等,我用zstd。 - disksize 是邏輯容量:聲明 16 G 不代表占 16 G 物理內存,實際占用只跟當前壓縮后的數(shù)據(jù)量成正比。
- same-filled page:整頁全是同一字節(jié)(最常見是全 0)的頁,只記一個標記,幾乎不占內存。
三、動手配置,以及我踩的坑
我用 systemd 的 zram-generator:配置驅動,開機自動重建,最省事。
第 1 步,安裝。
sudo apt update && sudo apt install -y systemd-zram-generator
第 2 步,寫配置。 我照搜到的教程寫了下面這版——后面會看到,這版是錯的:
# /etc/systemd/zram-generator.conf (錯誤示范) [zram0] zram-size = ram / 2 compression-algorithm = zstd swap-priority = 100
sudo systemctl daemon-reload sudo systemctl start systemd-zram-setup@zram0.service
第 3 步,一看結果,不對:
$ zramctl NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram0 zstd 4G 4K 64B 20K 16 [SWAP]
31 G 的一半應該是約 15.5 G,怎么只給了 4 G?而且 zstd 和優(yōu)先級都對——說明配置文件確實被讀了,單單尺寸不對。
先確認配置沒寫錯,文件就是 zram-size = ram / 2,沒問題。于是去翻日志:
$ sudo journalctl -b | grep -i 'unknown key' zram-generator[...]: Unknown key zram-size, ignoring.
原因出來了:它根本不認識 zram-size 這個鍵,直接忽略了。再看版本和手冊:
$ /lib/systemd/system-generators/zram-generator --version zram-generator 0.3.2 $ man 5 zram-generator.conf | grep -oE 'zram-fraction|max-zram-size|zram-size' | sort -u max-zram-size zram-fraction
手冊里只有 zram-fraction 和 max-zram-size,沒有 zram-size。zram-size(ram / 2 這種表達式語法)是 zram-generator 較新版本(1.x)才有的寫法;Ubuntu 22.04 裝的是 0.3.2,只認老鍵。zram-size 被忽略后,它退回到默認值——zram-fraction 默認 0.5、max-zram-size 默認 4096(MB),于是 min(0.5 × 31G, 4G) = 4G。這就是那 4 G 的來歷。
坑就坑在它靜默退回默認、只在日志里留一行 Unknown key:照抄新版教程、又不去翻 journal 的人,很容易就拿著一塊 4 G 的 zram 以為配好了。
第 4 步,改用這版認識的鍵:
# /etc/systemd/zram-generator.conf (正確) [zram0] zram-fraction = 0.5 max-zram-size = 16384 compression-algorithm = zstd swap-priority = 100
zram-fraction = 0.5 把邏輯容量設成內存的一半;max-zram-size = 16384(16 G)把默認 4 G 的上限抬上去,否則又會被砍回 4 G。重啟服務:
sudo systemctl restart systemd-zram-setup@zram0.service
$ zramctl NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram0 zstd 15.5G 4K 64B 20K 16 [SWAP] $ swapon --show NAME TYPE SIZE USED PRIO /swapfile file 2G 0B -2 /dev/zram0 partition 15.5G 0B 100
這次對了:15.5 G、zstd、優(yōu)先級 100,排在磁盤 swapfile(-2)前面。內核會先用 zram,用滿了才輪到磁盤。
第 5 步,提高 swappiness。 zram 換頁很便宜,我把 swappiness 調高,讓內核更早把冷頁壓進 zram,而不是死撐物理內存直到顛簸:
echo 'vm.swappiness = 150' | sudo tee /etc/sysctl.d/99-zram.conf sudo sysctl --system
四、開機自啟與持久化
不用額外做什么。zram-generator 是 systemd 生成器,每次開機會按 /etc/systemd/zram-generator.conf 自動重建 zram swap;swappiness 寫在 /etc/sysctl.d/99-zram.conf 里也是持久的。重啟后 zramctl 直接能看到那塊 15.5 G 的 zram0。
五、它平時占內存嗎?什么時候才被用到
配完我有個疑問:開了 15.5 G 的 zram,是不是平時就吃掉了我一大塊內存?答案是不會。先看一眼平時空閑時的狀態(tài):

圖 3. 內存富裕時(占用 37%)swap 用量為 0——zram 已就位但還沒被用到,此刻幾乎不占物理內存。圖中 Swap 總量 18.8 G = zram 15.5 GiB + 磁盤 swapfile 2 G。
兩個要點:
- zram 不預占內存。
disksize那 15.5 G 是邏輯容量,zram 實際占用的物理內存只跟當前壓進去的數(shù)據(jù)成正比。圖里 swap 用量是 0,所以 zram 此刻幾乎不吃物理內存——我配出 18.8 G 的 swap 池,并沒有讓可用內存少一點。 - 它按內存壓力隨用隨取,不是等"滿了"才用。內核按壓力漸進回收:內存越緊,越會把很久沒碰的冷頁壓進 zram,騰出物理內存給活躍數(shù)據(jù)。這個過程在遠沒到 OOM 之前就開始,所以 zram 是個提前介入的緩沖,而不是最后一刻的救命稻草。
swappiness = 150讓它在有壓力時更傾向于把冷頁換進便宜的 zram,而不是死扛物理內存。判斷系統(tǒng)有沒有壓力,最直接就是看 swap 用量:像圖里這樣接近 0,就說明很寬裕。
要親眼看它工作,等內存壓上去(比如 Memory 漲到 80% 以上)再看這幾項:
zramctl # DATA(原始) 會從 0 漲起來,TOTAL 是它實占的物理內存 cat /sys/block/zram0/mm_stat # 更細:orig_data_size compr_data_size mem_used_total ... swapon --show # /dev/zram0 的 USED 會 > 0
zramctl 的三列是關鍵:DATA 是寫入的原始數(shù)據(jù)量,COMPR 是壓縮后大小,TOTAL 是含分配器開銷的實際內存占用,DATA / TOTAL 就是實際壓縮比。還有個常見誤讀:配了 zram 后,監(jiān)控里 swap 用量會變活躍,這是正常的——這些"swap"并沒有離開內存;判斷它是否真起作用,看壓縮比,而不是 swap 用量數(shù)字。
六、zram 和 zswap 的區(qū)別
順帶說一下另一個容易混淆的東西 zswap。兩者都用壓縮省內存,但結構不同。

圖 2. zram 自成終點,壓縮數(shù)據(jù)常駐內存;zswap 是磁盤 swap 前的壓縮緩存,池滿后向磁盤回寫。
zram 是一塊獨立的內存盤,不需要后備磁盤,壓縮數(shù)據(jù)一直在內存里,填滿且沒有別的 swap 兜底時只能觸發(fā) OOM。zswap 是磁盤 swap 前面的一道壓縮緩存,必須配合磁盤 swap:頁先壓進內存池,池滿時按冷熱把最舊的頁解壓、寫回磁盤。
| 維度 | zram | zswap |
|---|---|---|
| 是否需要后備磁盤 | 不需要 | 需要真實 swap 分區(qū) |
| 壓縮數(shù)據(jù)存放 | 常駐內存 | 內存池,滿了寫回磁盤 |
| 池滿之后 | 觸發(fā) OOM | 向磁盤回寫溢出 |
| 適用 | swap 需求小且穩(wěn)定 | swap 需求大或不可預測 |
我的場景是想要一塊快的、自給自足的內存 swap,所以選 zram。
七、適用、注意,和實際效果
適合用 zram 的情況就是我這種:物理內存緊、CPU 有余量。
幾點注意:
- 不可壓縮數(shù)據(jù)會白耗 CPU。已壓縮的媒體、加密數(shù)據(jù)、隨機數(shù)據(jù)壓不動,壓縮比接近 1。這類負載可以配
writeback把它們寫回磁盤。 - zram 只能推遲 OOM,不能消除 OOM。我保留了默認開著的
systemd-oomd,讓它在內存真耗盡前殺掉失控進程,避免硬鎖死。 - CPU 滿載時會搶算力。zram 的前提是"內存緊、CPU 閑"。我的 CPU 大多數(shù)時候閑著,不虧。
實際效果,實話說:zram 不是真的加內存,而是讓現(xiàn)有內存靠壓縮多裝一些、并把 swap 變快。配完之后,內存沖高時不再卡死成那樣——以前是往 2 G 磁盤 swap 上顛簸,現(xiàn)在是壓進 zram、微秒級就能取回。effective 容量大概多出 8–12 G 量級。但如果工作負載常駐就要超過 32 G,唯一的真解還是加內存條;zram 是緩沖,不是無中生有。
以上就是Linux內存擴容從問題、原理、配置到踩坑修復的完整過程的詳細內容,更多關于Linux內存擴容指南的資料請關注腳本之家其它相關文章!
相關文章
Ubuntu查看端口占用情況以及系統(tǒng)詳情的命令大全
在Ubuntu下查看端口占用情況以及系統(tǒng)詳情有很多種方法,常見的包括使用lsof、netstat、fuser、ss、nmap等工具,其中,每種工具都有其特點和適用場景,需要根據(jù)具體的需求選擇合適的工具,文中通過代碼示例介紹的非常詳細,需要的朋友可以參考下2025-07-07
一文詳解如何在CentOS?7系統(tǒng)中掛載數(shù)據(jù)盤并修改默認掛載目錄
本文介紹了在CentOS7系統(tǒng)中掛載數(shù)據(jù)盤的方法,包括查看未掛載磁盤、分區(qū)、格式化、創(chuàng)建掛載目錄、臨時掛載及配置fstab實現(xiàn)永久掛載,詳細步驟確保數(shù)據(jù)盤成功掛載并保持在系統(tǒng)重啟后仍然掛載,需要的朋友可以參考下2026-04-04
Windows 和 Linux 上Redis的安裝守護進程配置方法
​ Redis是目前最常用的非關系型數(shù)據(jù)庫(NOSql)之一,常以Key-Value的形式存儲。這篇文章主要介紹了Windows 和 Linux 上Redis的安裝守護進程配置 ,需要的朋友可以參考下2019-06-06

