本文要点
zram是在内存里开一块压缩区域充当swap:换出的数据先压缩再存放,读写走内存而非磁盘,比磁盘 swap 快一个数量级- 创建三步:
zramctl -f -s 512M -a lz4创建设备 →mkswap初始化 →swapon启用 zramctl的DATA/COMPR两列直接展示压缩效果:内存压力下 37M 数据被压到 12.2M,省下约三分之二内存- 调优两点:zram 场景把
vm.swappiness调高(如 100)让系统优先用快的 zram,再把vm.page-cluster设为 0 避免按簇放大换入 - 开机自动启用用
zram-tools:改/etc/default/zramswap里的ALGO/SIZE/PRIORITY后systemctl enable --now zramswap - 所有命令均在 Ubuntu 24.04(内核 6.8)上真实执行验证
什么是 zram:把内存压缩后当 swap 用
上一篇文章《Linux 交换空间:从 swap 文件创建到 swappiness 调优》讲过 swap 是内存不足时的「兜底仓库」,把不活跃的内存页换出到磁盘腾地方。磁盘 swap 虽然能救命,但慢——内存是纳秒级、磁盘是毫秒级,差距近百万倍,高频换入换出会拖垮整个系统。
zram 换了个思路:它不把数据写到磁盘,而是在内存内部划出一块区域,用压缩算法把换出的页面压缩之后再存放。空间不够就压缩来凑——典型办公/服务器负载的压缩率有 2~4 倍,相当于 1G 内存当 2~4G 用。因为后端是内存,zram 的读写速度远快于磁盘 swap,这是它最大的价值。
工作流程如下:
内存页 --换出--> lz4/zstd 压缩 --> 存入 zram 块设备(仍在 RAM 里)
内存页 <--换入-- 解压还原 <-- 需要时从 zram 读回zram 的典型适用场景:
- 低内存 VPS / 云主机:1~2G 内存跑 Web 服务时,zram 能显著降低 OOM 概率,又比磁盘 swap 快得多;
- 服务器高可用:磁盘 swap 页频繁写入还会加速 SSD 磨损,zram 把写放大留在内存里,SSD 更省心;
- Android / 嵌入式:安卓手机默认就在用 zram 提升多任务能力。
与之相关的还有个 zswap:它不自己占一块内存,而是当缓存层架在内存与磁盘 swap 之间,先压缩放进内存、塞不下再写磁盘。zram 与 zswap 二选一即可,本篇文章聚焦 zram。查看当前的 zram 状态
动手前先看系统现状。zramctl(util-linux 自带)是查看 zram 的标准命令,无参数直接列出所有设备:
zramctl输出里每一列含义:
| 列 | 含义 |
|---|---|
NAME | zram 块设备路径,/dev/zram0、/dev/zram1… |
ALGORITHM | 当前使用的压缩算法(lz4 / lzo-rle / zstd 等) |
DISKSIZE | 设备容量,即「未压缩」的虚拟大小 |
DATA | 当前存进去的未压缩数据量 |
COMPR | 数据压缩后实际占用的量 |
TOTAL | 设备在内存里的总开销(含元数据),通常略大于 COMPR |
STREAMS | 并发压缩流的数量 |
MOUNTPOINT | [SWAP] 表示该设备正被当作交换空间使用 |
zram 是否参与交换,也能从 /proc/swaps 里看到——Type 列是 partition 的条目就来自 zram 这类块设备。
cat /proc/swaps内核支持哪些压缩算法,取决于 zram 模块:cat /sys/block/zram0/comp_algorithm(中括号里是当前选中项)。Ubuntu 24.04 内核 6.8 上能看到 lzo lzo-rle [lz4] lz4hc 842 zstd。各算法取舍:lz4 压缩最快、zstd 压缩率最高,lzo-rle 介于两者之间,日常推荐 lz4。
创建 zram 设备并启用为 swap
zram 设备是内核动态生成的块设备,三步走:创建 → 初始化 → 启用。
# 1. 确保 zram 模块已加载,并创建一个 512M、lz4 算法的 zram 设备
# -f 自动分配下一个空闲编号,-s 指定容量,-a 指定压缩算法
modprobe zram
zramctl -f -s 512M -a lz4
# 2. 格式化为交换空间
mkswap /dev/zram0
# 3. 启用(-p 可指定优先级,数值越大越优先被使用)
swapon -p 200 /dev/zram0四步串起来执行,再核对结果:

逐行看输出:
zramctl -f -s 512M -a lz4打印/dev/zram0,说明创建成功并拿到了编号 0;mkswap输出Setting up swapspace version 1, size = 512 MiB和随机 UUID(每次不同);zramctl里出现一行/dev/zram0 lz4 512M,MOUNTPOINT已变成[SWAP];/proc/swaps里新增partition类型的/dev/zram0(演示机原本已有一块 1G 的zram1在当 swap,所以编号从 0 开始并列显示,这并不冲突)。
注意此时 DISKSIZE 512M 只是「虚拟容量」——它在内存里实际占用的空间从 4K 开始,用多少压缩多少,不是一开始就吃掉 512M。这就是 zram 内存友好之处。
对比磁盘 swap 文件的创建流程(fallocate→chmod 600→mkswap→swapon),zram 省略了文件系统与磁盘空间两步,因为是纯内存设备,不需要chmod,也没有「磁盘写满」的顾虑。
验证压缩效果:内存压力实测
zram 宣称「压缩内存当 swap」,效果到底如何?用 stress 制造内存压力,观察换出到 zram 的数据被压缩了多少:
stress --vm 2 --vm-bytes 900M --timeout 90 >/dev/null 2>&1 & sleep 30; zramctl; free -h这条命令后台启动两个各占 900M 的压测进程(总计 1.8G,超过这台机器 1.8G 内存),等 30 秒后看实时状态:

看 zramctl 里 /dev/zram0 那一行:
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 lz4 512M 37M 12.2M 13.8M 2 [SWAP]DATA 37M:系统向 zram 换出了 37M 的原始内存页;COMPR 12.2M:压缩后只占 12.2M,压缩率约 3 倍;TOTAL 13.8M:算上 zram 的元数据开销,实际从 1.8G 物理内存里「挤」出的约 13.8M,就换来了 37M 的临时空间。
这正是 zram 的核心价值:内存翻倍的代价只是几 M 到几十 M 的压缩开销。同时也说明一个道理——zram 的压缩率取决于数据本身的规律性,stress 这类重复性高的数据能压到 3 倍,真实业务进程一般也有 2~4 倍;如果全是高熵数据(如压缩包、加密流量),压缩率会很低,但至少不会比磁盘 swap 更糟。
更底层:zram 的统计文件
zramctl 只是把内核暴露的统计读了出来。内核 6.8 之后 zram 的内存统计合并到了 /sys/block/zram0/mm_stat:
cat /sys/block/zram0/mm_stat
# 输出形如:4096 65 20480 0 20480 0 0 0 0前三个数字分别对应:原始数据大小(orig_data_size)、压缩后大小(compr_data_size)、实际内存占用(mem_used_total)。老内核(6.8 之前)则是 orig_data_size、compr_data_size、mem_used_total 三个独立文件。理解这一点,遇到旧教程对不上时就不会懵。
调优:swappiness 与 page-cluster
swap 篇里建议磁盘 swap 场景把 vm.swappiness 调低到 10,减少磁盘写入。但 zram 的「磁盘」其实是内存,写多少次都不磨损、速度又快,所以 zram 场景的逻辑完全反过来——鼓励系统优先用 zram,把换出尽量留在内存里:
# 让系统更积极地把数据换出到(速度快的)zram
sysctl vm.swappiness=100
# 永久生效
echo 'vm.swappiness=100' > /etc/sysctl.d/99-zram.conf
sysctl -p /etc/sysctl.d/99-zram.conf更有针对性的一个参数是 vm.page-cluster。它控制一次换入/换出多少个页面(默认 3 = 2³ = 8 页一批),这是为磁盘设计的——磁盘连续读 8 页比单读快。但 zram 的随机读走内存,批次预取只会白白放大压缩解压的工作量,社区普遍建议对 zram 场景设 0:
echo 'vm.page-cluster=0' >> /etc/sysctl.d/99-zram.conf
sysctl -p /etc/sysctl.d/99-zram.conf一句话总结调优:磁盘 swap 场景 swappiness 调低(少碰磁盘),zram 场景 swappiness 调高、page-cluster 归零(多压内存、别批量预取)。
开机自动启用:zram-tools
重启后 zram 设备会随内核模块消失,手动创建的 swap 自然也没了。开机自动启用最省心的方式是装 zram-tools(Ubuntu/Debian 官方包):
apt install zram-tools它提供一个 zramswap systemd 服务,配置写在 /etc/default/zramswap:
# 压缩算法:速度 lz4 > zstd > lzo;压缩率 zstd > lzo > lz4
ALGO=lz4
# 每个 zram 设备的容量(MiB);设了 PERCENT 时按内存百分比计算并覆盖 SIZE
SIZE=512
# swap 优先级,数值越大越先被使用,建议高于磁盘 swap(默认 100)
PRIORITY=200配好生效并确认:

图中 grep 过滤掉注释后,有效配置就是三行 ALGO=lz4 / SIZE=512 / PRIORITY=200;重启服务后 systemctl is-active zramswap 输出 active,zramctl 里出现 512M 的 lz4 swap——下次开机它也会自动创建。
systemctl enable --now zramswap # 开机自启 + 立即启动⚠️ 一个容易踩的坑:zramswap服务默认操作/dev/zram0。如果系统里已经手动建过其他 zram 设备(比如本文前面的演示),编号错位会导致服务报错comp_algorithm: No such file or directory。遇到时先清掉多余设备再启动:swapoff 你的设备→zramctl -r 设备,或者干脆modprobe -r zram卸载模块后重启服务。
另外还有一套 systemd 原生方案 zram-generator(Fedora 等发行版默认方案),通过 /etc/systemd/zram-generator.conf 的 INI 配置声明设备,喜欢声明式配置的可以了解。Ubuntu 上 apt install zram-generator 即可,二选一,不要两套同时上。
关闭与移除 zram
回收 zram 的顺序与创建相反:先关 swap、再删设备、最后可卸载模块。
# 1. 关闭 swap(数据迁回内存,需保证内存够用)
swapoff /dev/zram0
# 2. 移除 zram 设备,释放它占用的内存
zramctl -r /dev/zram0
# 3. 确认所有 zram 设备都不再需要后,可卸载内核模块
modprobe -r zram如果用了 zram-tools,关闭则直接 systemctl stop zramswap,并确认 /etc/fstab 里没有残留的 zram 相关行(zram-tools 走 systemd 单元,本身不写 fstab)。
常见问题排查
1. zramctl -f 分配的编号不是 0,或者 zramswap 服务报 comp_algorithm: No such file or directory
zram 设备编号按「最小空闲号」分配,已有设备时新设备会往后排;zram-tools 又硬编码操作 /dev/zram0,两者叠加就会出错。清理多余设备或用 zram-generator 即可,见上文。
2. 内存压力下 swap 数据没进 zram,磁盘 swap 反而被写满
检查优先级:cat /proc/swaps 看 Priority 列,zram 的优先级要高于磁盘 swap 才会被优先使用。创建时用 swapon -p 指定,或 zram-tools 里设 PRIORITY(建议 100+)。
3. zram 被写满怎么办
DISKSIZE 是上限,写满后会继续溢出到磁盘 swap(如果配置了)。可以用 mem_limit 限制单个设备的内存占用上限(写成字节数),或调大 SIZE。
4. swapoff 很慢甚至卡住
zram 里存着大量待迁回内存的数据,而内存又紧张时,swapoff 会阻塞等待。先释放内存(停掉压测、清缓存)再操作。
评论 (0)
暂无评论,快来抢沙发吧!