【知识】小内存设备救星:zram

转载请注明出处:小锋学长生活大爆炸xfxuezhagn.cn

如果本文帮助到了你,欢迎点赞、收藏、关注哦~

小内存设备救星:zram + lz4 让 4G 内存也能流畅跑 Docker

适用于:飞牛私有云 fnOS ARM 版 / 电视盒子 / 树莓派 / 各类小内存 ARM 设备

一、问题背景

在 ARM 盒子(如电视盒子、开发板)上运行 NAS 系统时,经常遇到这样的困境:

  • • 物理内存只有 3-4GB
  • • 运行 Docker 容器后内存迅速耗尽
  • • 系统开始频繁使用磁盘 swap,导致卡顿甚至卡死
  • • 磁盘 swap 放在 eMMC/SD 卡上,读写速度慢且消耗寿命

传统 swap 的痛点

痛点 说明
速度慢 eMMC/SD 卡读写仅 50-100MB/s
寿命短 频繁擦写加速存储芯片老化
空间占用 swap 文件占用宝贵的磁盘空间
体验差 一旦触发磁盘 swap,系统明显卡顿

典型场景:4G 内存跑 3-4 个 Docker 容器,内存占满后开始 swap,NAS 管理界面都打不开。

二、zram 是什么?

2.1 核心概念

zram(以前叫 compcache)是 Linux 内核的一个模块,它:

    1. 物理内存中划分一块区域
    1. 将准备 swap 出去的数据实时压缩后存储
    1. 用 CPU 算力换取内存空间

一句话总结:用内存的一部分假装成磁盘 swap,但数据是压缩存放的。

2.2 为什么比磁盘 swap 快?

对比项 磁盘 swap zram
存储介质 eMMC/SSD/HDD 内存(RAM)
读写速度 50-500 MB/s 数 GB/s(内存速度)
延迟 毫秒级 微秒级
寿命影响 消耗磁盘寿命
额外开销 CPU 压缩/解压

关键优势:内存访问速度是磁盘的 10-100 倍,即使加上压缩开销,zram 仍然比磁盘 swap 快得多。

2.3 压缩率如何?

zram 的压缩效果取决于数据类型:

数据类型 压缩率 说明
文本、代码、重复数据 2:1 ~ 3:1 省一半到三分之二内存
已压缩数据(图片、视频、加密流量) 接近 1:1 省不了多少
混合场景(日常 NAS 使用) 1.5:1 ~ 3:1 通常能节省 30-50% 的空间

举例:分配 2G zram,实际等效可能达到 3-4G 的 swap 容量。

2.4 实际效果

以学长的设备为例(3.6G 物理内存):

复制代码
  $ zramctl
NAME       ALGORITHM DISKSIZE  DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 lz4           1.8G 129.3M 37.6M 39.4M       6 [SWAP]
  • DATA 129.3M → 原始数据 129MB
  • COMPR 37.6M → 压缩后仅 37.6MB
  • 压缩率约 3.4:1,效果极佳

三、lz4 压缩算法

3.1 zram 支持哪些算法?

Linux 内核通常支持以下算法:

算法 压缩速度 压缩率 CPU 占用 适用场景
lz4 极快 一般 很低 小内存设备首选
lzo / lzo-rle 稍好 内核默认
lz4hc 较好 平衡选择
zstd 中等 很好 中高 大内存服务器
deflate 兼容性需求
842 很快 一般 很低 特定硬件加速

3.2 为什么选 lz4?

对于 ARM 盒子 / 小内存设备:

    1. 压缩/解压速度最快 --- 减少 CPU 开销,系统更流畅
    1. CPU 占用最低 --- ARM 处理器性能有限,省 CPU 就是省性能
    1. 延迟最低 --- swap 操作本身已经够慢了,压缩不能成为瓶颈
    1. 实时性好 --- 适合交互式场景,不会因为压缩导致卡顿

牺牲:压缩率比 zstd 差 10-20%,但速度提升 3-5 倍,对小设备来说完全值得。

3.3 如何查看和切换算法

复制代码
  # 查看当前算法(方括号中为当前算法)
cat /sys/block/zram0/comp_algorithm
# 输出示例:[lzo-rle] lzo lz4 lz4hc zstd deflate 842

# 切换为 lz4(需先关闭 swap)
sudo swapoff /dev/zram0
echo lz4 | sudo tee /sys/block/zram0/comp_algorithm
sudo mkswap /dev/zram0
sudo swapon /dev/zram0

四、完整配置流程

4.1 环境准备

FnNAS / fnOS(飞牛私有云 ARM 版) 为例,通过 SSH 登录:

bash 复制代码
    
    
    
  ssh root@你的设备IP

4.2 检查当前状态

复制代码
  # 查看内存和 swap 使用情况
free -h

# 查看当前 swap 详情
swapon --show

# 查看 zram 状态(如果有)
zramctl

4.3 清理旧的 zram 配置(如有)

如果系统之前配置过 zram 但失败了,先清理:

复制代码
  # 停止可能冲突的服务
sudo systemctl stop systemd-zram-setup@zram0.service 2>/dev/null
sudo systemctl stop zramswap.service 2>/dev/null

# 关闭所有 swap
sudo swapoff -a

# 重置所有 zram 设备
sudo zramctl --reset /dev/zram0 2>/dev/null
sudo zramctl --reset /dev/zram1 2>/dev/null

4.4 创建 zram 设备

复制代码
  # 加载 zram 模块
sudo modprobe zram num_devices=1

# 创建 zram0 设备,大小 2GB,算法 lz4
sudo zramctl /dev/zram0 --size 2G --algorithm lz4

# 如果 zramctl 不支持 --algorithm 参数,用 sysfs:
# echo lz4 | sudo tee /sys/block/zram0/comp_algorithm
# echo 2G | sudo tee /sys/block/zram0/disksize

大小建议:zram 大小通常设为物理内存的 50%-100%。4G 内存设 2G,8G 内存设 4G。

4.5 启用 zram swap

复制代码
  # 格式化为 swap
sudo mkswap /dev/zram0

# 启用,并设置高优先级(-p 100)
# 优先级越高,系统越优先使用
sudo swapon /dev/zram0 -p 100

# 重新启用磁盘 swap(作为兜底,优先级低)
sudo swapon /mnt/.swap/swapfile

4.6 验证配置

复制代码
  # 查看内存状态
free -h

# 查看 swap 优先级
swapon --show

# 查看 zram 详情
zramctl --output-all

预期输出:

复制代码
  $ free -h
               total        used        free      shared  buff/cache   available
Mem:           3.6Gi       2.7Gi       100Mi       280Mi       1.2Gi       901Mi
Swap:          3.0Gi       591Mi       2.4Gi

$ swapon --show
NAME                TYPE       SIZE   USED PRIO
/mnt/.swap/swapfile file      1024M 256.2M   -2      # 磁盘 swap,兜底
/dev/zram0          partition    2G 335.3M  100       # zram,优先使用

$ zramctl
NAME       ALGORITHM DISKSIZE  DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 lz4             2G 23.3M  8.5M  8.5M       6 [SWAP]

4.7 设置开机自动生效

创建 systemd 服务:

复制代码
  sudo tee /etc/systemd/system/zram-swap.service > /dev/null << 'EOF'
[Unit]
Description=Zram Swap with lz4
After=local-fs.target

[Service]
Type=oneshot
ExecStartPre=-/sbin/modprobe zram
ExecStartPre=-/sbin/zramctl --reset /dev/zram0
ExecStart=/sbin/zramctl /dev/zram0 --size 2G --algorithm lz4
ExecStart=/sbin/mkswap /dev/zram0
ExecStart=/sbin/swapon /dev/zram0 -p 100
ExecStart=/sbin/swapon /mnt/.swap/swapfile
ExecStop=/sbin/swapoff /dev/zram0
ExecStop=/sbin/swapoff /mnt/.swap/swapfile
ExecStop=/sbin/zramctl --reset /dev/zram0
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable zram-swap
sudo systemctl start zram-swap

五、进阶调优

5.1 调整 swappiness

控制系统使用 swap 的倾向:

复制代码
  # 查看当前值(默认通常 60)
cat /proc/sys/vm/swappiness

# 临时设为 10(减少不必要的 swap,保留给真正需要时)
echo 10 | sudo tee /proc/sys/vm/swappiness

# 永久生效
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
含义
0 尽量不用 swap
10-30 保守使用,适合小内存设备
60 默认,平衡
100 积极使用 swap

5.2 监控 zram 效率

复制代码
  # 查看压缩统计
cat /sys/block/zram0/mm_stat

# 查看压缩率
cat /sys/block/zram0/comp_data_size
cat /sys/block/zram0/orig_data_size

# 实时查看
cat /proc/swaps

5.3 多 zram 设备(多核优化)

如果 CPU 核心多,可以创建多个 zram 设备,每个绑定一个核心:

复制代码
  # 创建 4 个 zram 设备(假设 4 核)
sudo modprobe zram num_devices=4

# 每个 512M,总共 2G
for i in 0 1 2 3; do
    sudo zramctl /dev/zram$i --size 512M --algorithm lz4
    sudo mkswap /dev/zram$i
    sudo swapon /dev/zram$i -p 100
done

现代内核通常会自动处理多线程,单设备也足够好。

六、常见问题

Q1: zram 和磁盘 swap 可以同时用吗?

可以,而且推荐。zram 优先级设高(如 100),磁盘 swap 优先级设低(如 -2)。系统会先用 zram,满了才用磁盘 swap。

Q2: zram 会消耗很多 CPU 吗?

lz4 算法下几乎无感。压缩/解压速度达到数 GB/s,对小数据量的 swap 操作来说,CPU 开销可以忽略。

Q3: 为什么 swapon 报 "Invalid argument"?

常见原因:

  • • 文件系统不支持 swap(如 Btrfs、ZFS)
  • • zram 设备未正确初始化
  • • 设备正被占用

Q4: 重启后 zram 消失?

需要创建 systemd 服务或加入 /etc/rc.local 实现开机自动配置。

Q5: 4G 内存设多大 zram?

建议 2G。zram 太大可能挤压正常内存使用,太小则效果不明显。

Q6: 为什么 Btrfs 上不能放 swap 文件?

Btrfs 不支持传统的 swap file(或支持但条件苛刻且有风险)。解决方案:

  • • 使用 zram(推荐)
  • • 创建独立的 swap 分区
  • • 使用 zram 替代磁盘 swap

七、总结

方案 速度 寿命 空间 适用场景
无 swap --- --- --- 内存极大时
磁盘 swap 消耗磁盘 占用磁盘 大内存服务器
zram + lz4 无影响 内存内压缩 小内存设备首选

对于 ARM 盒子、NAS、树莓派等小内存设备,zram + lz4 是最优解

  • • ✅ 速度接近内存,比磁盘 swap 快 10 倍以上
  • • ✅ 不消耗磁盘寿命
  • • ✅ 不占用磁盘空间
  • • ✅ CPU 开销极低(lz4 算法)
  • • ✅ 配置简单,效果立竿见影

附录:一条命令速配

复制代码
  sudo bash -c 'modprobe zram; zramctl --reset /dev/zram0 2>/dev/null; zramctl /dev/zram0 --size 2G --algorithm lz4; mkswap /dev/zram0; swapon /dev/zram0 -p 100; swapon /mnt/.swap/swapfile 2>/dev/null; echo "zram OK"'

执行后运行 free -hzramctl 验证即可。

本文基于 fnOS / FnNAS ARM 版实测整理,适用于各类小内存 Linux 设备。