# Linux 内存不足？ZRAM 压缩方案详解与实战配置


<!-- more -->

Linux 设备内存不够用是常态，尤其是小内存 VPS、树莓派、旧笔记本等场景。传统做法是加 SWAP 分区，但很多人发现加了之后反而更卡了。

这篇文章从底层原理出发，对比 SWAP 和 ZRAM 两种方案，帮你搞清楚：**什么场景该用什么，以及怎么配置。**

## SWAP 的本质：用磁盘冒充内存

SWAP 的工作原理很简单 — 内存放不下的数据写到磁盘上，需要时再读回来。问题出在「磁盘」这两个字上。

**磁盘 IO 和内存 IO 的差距是数量级的：**

| 操作 | 延迟 |
|------|------|
| 内存访问 | ~100 纳秒 |
| SSD 随机读 | ~100 微秒（慢 1000 倍） |
| HDD 随机读 | ~10 毫秒（慢 100000 倍） |

这意味着当系统开始频繁使用 SWAP（所谓的 swap thrashing），进程会频繁被阻塞等待磁盘 IO，**系统表现就是：卡顿、假死、鼠标能动但点啥都没反应。**

而且 SWAP 对 SSD 还有副作用 — 频繁的写入会加速闪存颗粒磨损（虽然现代 SSD 寿命已经很长了，但在高 SWAP 负载下依然不可忽视）。

**SWAP 适合的场景：**

- 磁盘是 NVMe SSD，IO 延迟足够低
- 内存基本够用，SWAP 只是偶尔的应急缓冲
- 不在意偶尔的卡顿，只要不 OOM（Out of Memory）被杀进程

**SWAP 不适合的场景：**

- 磁盘是 HDD 或低速 eMMC
- 内存经常吃紧，SWAP 会成为常态而非应急
- 需要稳定低延迟的服务（数据库、API 服务）

## ZRAM 的本质：在内存里「挤」出更多空间

ZRAM 完全不碰磁盘。它在内存中创建一个压缩块设备，把不常用的内存页压缩后存放。需要时解压还原。

核心优势：

1. **数据始终在内存中** — 没有磁盘 IO 瓶颈，延迟是微秒级
2. **压缩比通常 2:1 ~ 3:1** — 1GB 物理内存可以当 2~3GB 用
3. **对 SSD 友好** — 减少磁盘写入，延长寿命

隐性代价：

- **CPU 开销**：压缩和解压需要 CPU 计算。lz4 算法已经很轻量了，但在 CPU 本身就是瓶颈的设备上（极低端的 ARM 芯片），还是会有影响
- **不能无限压缩**：物理内存耗尽后 ZRAM 也救不了你，仍然需要 SWAP 兜底

## 如何选择：决策流程

不要简单地说「磁盘差就用 ZRAM」，应该根据实际情况分层决策：

```
你的磁盘是什么类型？
├── 纯 NVMe SSD
│   ├── 内存基本够用（偶尔不足）→ SWAP 足矣
│   └── 内存经常紧张 → ZRAM 优先 + 小容量 SWAP 兜底
├── 纯 SATA SSD
│   └── 推荐 ZRAM 为主 + 小 SWAP 兜底
├── SSD + HDD 混装
│   └── ZRAM 为主，SWAP 放 SSD（不放 HDD）
├── 纯 HDD / eMMC
│   └── 必须用 ZRAM，尽量不用 SWAP
└── VPS（云盘通常 IO 较好）
    └── ZRAM 为主，可加小 SWAP 防止 OOM
```

**总结一句话：磁盘越差，ZRAM 越重要；内存越小，ZRAM 越必要。**

## ZRAM 配置实战

### 1. 安装工具

```bash
sudo apt update && sudo apt install -y zram-tools
```

### 2. 配置参数

编辑配置文件：

```bash
sudo nano /etc/default/zramswap
```

填入以下内容：

```ini
ALGO=lz4          # 高速压缩算法，兼顾速度与压缩率
PERCENT=50        # 占用物理内存的 50% 作为 ZRAM 空间
PRIORITY=100      # 优先使用 ZRAM，优于磁盘 SWAP
```

**PERCENT 怎么定？**

| 物理内存 | 建议 PERCENT | 说明 |
|----------|-------------|------|
| ≤ 512MB | 100% | 内存太小，压缩空间越多越好 |
| 1GB ~ 2GB | 75% ~ 100% | 根据负载调整 |
| 4GB ~ 8GB | 50% | 平衡压缩空间和可用内存 |
| > 8GB | 25% ~ 50% | 通常够用，不需要激进压缩 |

注意：PERCENT 不是越大越好。ZRAM 本身占用物理内存，设太高会挤压正常程序的可用内存，反而加重内存压力。50% 是一个比较安全的起步值，可以根据实际使用情况调整。

### 3. 启动并设置开机自启

```bash
sudo systemctl enable --now zramswap.service
```

### 4. 验证是否生效

```bash
swapon --show
```

看到 `/dev/zram0` 即成功：

```
NAME       TYPE      SIZE USED PRIO
/dev/zram0 partition  XXX   0  100
```

### 5. 监控压缩状态

```bash
zramctl
```

输出示例：

```
NAME       ALGORITHM DISKSIZE  DATA  COMPR  TOTAL STREAMS MOUNTPOINT
/dev/zram0 lz4         XXXG  XXXM  XXXXX  XXXXX       N  [SWAP]
```

关注 `DATA`（原始数据大小）和 `COMPR`（压缩后大小）的比例，这就是实际压缩比。

更详细的统计：

```bash
cat /sys/block/zram0/mm_stat
```

## ZRAM + SWAP 混合策略（推荐）

ZRAM 虽好，但物理内存终究有限。当压缩后的数据也塞不下时，系统会 OOM。**建议 ZRAM + 磁盘 SWAP 混合使用**，通过 PRIORITY 控制优先级：

- **PRIORITY=100** 的 ZRAM 作为第一层 — 常规内存压力由它吸收
- **PRIORITY=10** 的磁盘 SWAP 作为兜底 — 极端情况防止 OOM

这样系统会先用 ZRAM（快），ZRAM 满了才慢慢溢出到磁盘 SWAP（慢但不会死）。

如果你之前已经有 SWAP 分区，不需要删掉，ZRAM 的 PRIORITY 设高就行，内核会自动按优先级选择。

## 常见问题

**Q：ZRAM 会占用我的可用内存吗？**

是的。ZRAM 设备本身预分配一部分内存。但这是用少量内存换取更大的压缩空间，净效果是正的。以 50% 比例为例，2GB 内存的设备会划出 1GB 做 ZRAM，但压缩后等效于 2~3GB 的 SWAP 空间，总体可用内存是增加的。

**Q：ZRAM 会导致 CPU 占用升高吗？**

会有小幅增加，lz4 算法的 CPU 开销非常低。在树莓派 4 这种 ARM 设备上测试，SWAP 操作期间的 CPU 额外占用通常在 3%~8%。只有在极端高频内存操作场景下才需要关注。

**Q：我该不该关掉原来的 SWAP？**

通常不需要。保留原有 SWAP 并设低优先级即可，让 ZRAM 优先处理。如果你的磁盘是 HDD，可以考虑缩小或关闭 SWAP，避免频繁的磁盘写入。

**Q：压缩算法选 lz4 还是 zstd？**

日常使用选 lz4，压缩/解压速度极快，延迟最低。如果内存极其紧张（如 256MB 设备），可以考虑 zstd，压缩比更高（约比 lz4 高 20%~30%），但 CPU 开销更大。对于大多数场景，lz4 是最优选择。

