为Linux服务器开启ZRAM来节约内存

Kaku Lv4

前言

最近在折腾几台小内存的VPS,发现内存经常不够用,交换分区又会拖慢系统性能。偶然发现了ZRAM这个好东西,可以在内存中创建压缩的交换空间,既能缓解内存压力,又不会有传统swap的IO瓶颈。今天就来分享一下如何在Linux服务器上配置ZRAM。

什么是ZRAM

ZRAM(压缩RAM)是Linux内核的一个模块,它可以在内存中创建压缩的块设备。简单来说,就是把一部分内存拿出来做压缩存储,当系统内存不足时,可以将不常用的数据压缩后存储在ZRAM中,而不是写入硬盘的swap分区。

ZRAM的优势

  • 性能好:比传统硬盘swap快得多,因为都在内存中
  • 节省内存:通过压缩可以获得2-3倍的有效内存空间
  • 减少磨损:减少对SSD的写入,延长硬盘寿命
  • 低延迟:访问速度远超传统swap

ZRAM的工作原理

ZRAM的原理是划分一块内存区域作为虚拟的块设备(支持透明压缩的内存文件系统),当系统内存不足出现页面交换时,将原本应该交换到硬盘的页面压缩后存放在内存中。

核心机制:

  1. 利用Swap优先级:ZRAM作为高优先级Swap设备
  2. 透明压缩:自动压缩和解压缩数据
  3. 内存分层:形成 RAM -> ZRAM -> 硬盘Swap 的多层存储
  4. 压缩算法选择:支持lzo、lz4、zstd等多种压缩算法

由于ZRAM没有改变Linux内存模型的基本结构,因此可以与现有的Swap机制完美集成,这也是为什么它能在Android等内存受限的环境中得到广泛应用。

检查系统支持

首先检查你的系统是否支持ZRAM:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 检查内核版本(ZRAM需要3.14+)
uname -r

# 使用modinfo检查ZRAM模块支持(推荐方法)
modinfo zram

# 检查内核配置
grep CONFIG_ZRAM /boot/config-$(uname -r)

# 检查内核模块
lsmod | grep zram

# 如果没有输出,尝试加载模块
sudo modprobe zram

# 检查是否加载成功
lsmod | grep zram

注意事项:

  • ZRAM从Linux 3.14开始正式进入主线内核
  • 部分VPS使用Xen、OpenVZ等虚拟化技术,内核版本可能较老
  • 使用modinfo zram是最可靠的检查方法
  • CentOS 7虽然内核版本是3.10,但也支持ZRAM

大部分现代Linux发行版都内置了ZRAM支持,如果上面的命令有输出就说明系统支持。

手动配置ZRAM

基本配置步骤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1. 加载zram模块
sudo modprobe zram

# 2. 创建zram设备(这里创建一个设备)
echo 1 | sudo tee /sys/class/zram-control/hot_add

# 3. 设置压缩算法(可选,默认是lzo)
echo lz4 | sudo tee /sys/block/zram0/comp_algorithm

# 4. 设置ZRAM大小(这里设置为1GB)
echo 1G | sudo tee /sys/block/zram0/disksize

# 5. 格式化为swap
sudo mkswap /dev/zram0

# 6. 启用swap
sudo swapon /dev/zram0

# 7. 设置优先级(可选,数值越高优先级越高)
sudo swapon /dev/zram0 -p 100

查看ZRAM状态

1
2
3
4
5
6
7
8
# 查看swap状态
cat /proc/swaps

# 查看ZRAM详细信息
cat /sys/block/zram0/stat

# 查看压缩统计
cat /sys/block/zram0/mm_stat

一键脚本安装

如果觉得手动配置比较麻烦,可以使用GitHub上的一键脚本来快速部署ZRAM。这里推荐使用spiritLHLS大佬开源的addzram脚本:

1
curl -L https://raw.githubusercontent.com/spiritLHLS/addzram/main/addzram.sh -o addzram.sh && chmod +x addzram.sh && bash addzram.sh

这个脚本会自动:

  • 检测系统环境和内核支持
  • 自动配置合适的ZRAM大小
  • 设置开机自启动
  • 选择最优的压缩算法

脚本执行后会提示配置结果,非常方便快捷。感谢 spiritLHLS 提供的优秀脚本!

对于新手或者想要快速部署的用户,强烈推荐使用这个一键脚本。如果你想要更精细的控制或者学习具体的配置过程,可以继续看下面的手动配置方法。

自动化配置

如果选择手动配置,重启后会失效,我们需要设置开机自动启用。

方法一:使用systemd服务

创建一个systemd服务文件:

1
sudo nano /etc/systemd/system/zram.service

写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=ZRAM swap service
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/zram-start.sh
ExecStop=/usr/local/bin/zram-stop.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

创建启动脚本:

1
sudo nano /usr/local/bin/zram-start.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
# ZRAM 启动脚本

# 加载模块
modprobe zram

# 创建设备
echo 1 > /sys/class/zram-control/hot_add

# 设置压缩算法
echo lz4 > /sys/block/zram0/comp_algorithm

# 设置大小(这里设置为物理内存的一半)
MEMORY_SIZE=$(free -b | awk '/^Mem:/ {print $2}')
ZRAM_SIZE=$((MEMORY_SIZE / 2))
echo $ZRAM_SIZE > /sys/block/zram0/disksize

# 格式化并启用
mkswap /dev/zram0
swapon /dev/zram0 -p 100

echo "ZRAM swap enabled"

创建停止脚本:

1
sudo nano /usr/local/bin/zram-stop.sh
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# ZRAM 停止脚本

# 关闭swap
swapoff /dev/zram0

# 删除设备
echo 0 > /sys/class/zram-control/hot_remove

echo "ZRAM swap disabled"

设置脚本权限并启用服务:

1
2
3
4
5
6
7
8
9
sudo chmod +x /usr/local/bin/zram-start.sh
sudo chmod +x /usr/local/bin/zram-stop.sh

# 启用服务
sudo systemctl enable zram.service
sudo systemctl start zram.service

# 检查状态
sudo systemctl status zram.service

方法二:使用zram-tools包

对于Ubuntu/Debian系统,可以直接使用官方包:

1
2
3
4
5
6
# 安装zram-tools
sudo apt update
sudo apt install zram-tools

# 编辑配置文件
sudo nano /etc/default/zramswap

配置文件内容:

1
2
3
4
5
6
7
8
# 启用ZRAM
ZRAM_ENABLED=true

# 设置大小(50表示物理内存的50%)
ZRAM_SIZE_PERCENT=50

# 设置压缩算法
ZRAM_ALGORITHM=lz4

启用服务:

1
2
sudo systemctl enable zramswap
sudo systemctl start zramswap

优化配置

选择合适的压缩算法

不同的压缩算法有不同的特点:

1
2
3
4
5
6
7
8
# 查看支持的压缩算法
cat /sys/block/zram0/comp_algorithm

# 常见算法对比:
# lzo: 速度快,压缩率一般
# lz4: 速度很快,压缩率中等(推荐)
# zstd: 压缩率高,速度中等
# lzo-rle: LZO的改进版本

个人推荐使用lz4,在速度和压缩率之间取得了很好的平衡。

设置合适的大小

ZRAM大小建议:

  • 小内存系统(1-2GB):设置为物理内存的50-100%
  • 中等内存系统(4-8GB):设置为物理内存的25-50%
  • 大内存系统(16GB+):设置为固定大小如2-4GB

调整swappiness

1
2
3
4
5
6
7
8
# 查看当前值
cat /proc/sys/vm/swappiness

# 临时设置(建议设置为60-80)
sudo sysctl vm.swappiness=80

# 永久设置
echo 'vm.swappiness=80' | sudo tee -a /etc/sysctl.conf

关于swappiness的重要说明:

很多人对swappiness参数存在误解,认为它是一个简单的百分比。实际上,swappiness控制的是内核在内存回收时选择回收匿名页(需要swap)还是文件页(直接丢弃或写回)的倾向性。

  • 默认值60:倾向于优先回收文件页
  • 设置为100:平等对待匿名页和文件页
  • 大于100:更倾向于回收匿名页(使用swap)

对于ZRAM环境,由于ZRAM的访问速度远快于硬盘swap(约30倍差距 vs 传统swap的300+倍差距),我们可以更激进地使用swap,建议设置为80-100之间。

什么时候ZRAM才会被使用?

ZRAM只有在系统内存压力达到一定程度时才会被使用。Linux使用内存水位线(Watermark)机制:

  • 高水位线:内存充足,无需回收
  • 低水位线:开始内存回收,kswapd0线程激活
  • 最小水位线:内存严重不足,开始同步回收

只有当可用内存低于低水位线时,系统才会根据swappiness设置决定是否使用ZRAM。

监控和维护

查看ZRAM状态

使用zramctl工具(推荐):

1
2
3
4
5
6
7
8
9
10
11
12
# 安装util-linux(如果没有zramctl命令)
# Ubuntu/Debian
sudo apt install util-linux

# CentOS/RHEL
sudo yum install util-linux

# 查看ZRAM状态
zramctl

# 查看详细信息
zramctl --output-all

直接查看系统文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 查看基本统计信息
cat /sys/block/zram0/mm_stat

# 输出说明:
# orig_data_size - 压缩前大小 (Byte)
# compr_data_size - 压缩后大小 (Byte)
# mem_used_total - 总内存消耗,包含元数据 (Byte)
# mem_limit - 内存消耗限制 (Byte)
# mem_used_max - 历史最高内存用量 (Byte)
# same_pages - 相同页数
# pages_compacted - 历史压缩页数
# huge_pages - 无法压缩的页数

# 查看压缩算法
cat /sys/block/zram0/comp_algorithm

# 计算压缩率
# 压缩率 = 压缩前大小 / 压缩后大小

监控ZRAM使用情况

创建一个简单的监控脚本:

1
sudo nano /usr/local/bin/zram-monitor.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash
echo "=== ZRAM 状态监控 ==="
echo "时间: $(date)"
echo

echo "内存使用情况:"
free -h
echo

echo "Swap使用情况:"
cat /proc/swaps
echo

echo "ZRAM详细信息:"
if command -v zramctl &> /dev/null; then
zramctl
else
for i in /sys/block/zram*/mm_stat; do
if [ -r "$i" ]; then
dev=$(basename $(dirname $i))
echo "设备: $dev"
# 读取mm_stat文件的各项数据
read orig_size compr_size mem_used mem_limit mem_max same_pages pages_compacted huge_pages < "$i"
echo " 压缩前大小: $(numfmt --to=iec $orig_size)"
echo " 压缩后大小: $(numfmt --to=iec $compr_size)"
if [ "$orig_size" -gt 0 ]; then
compression_ratio=$(echo "scale=2; $orig_size / $compr_size" | bc -l)
echo " 压缩比: ${compression_ratio}:1"
fi
echo " 内存使用: $(numfmt --to=iec $mem_used)"
echo
fi
done
fi

echo "内存水位线信息:"
if [ -r /proc/zoneinfo ]; then
awk '/Node 0, zone.*Normal/,/^$/ {
if ($1 == "pages") print " " $1 " " $2 ": " $3 " pages"
else if ($1 ~ /^(min|low|high)$/) print " " $1 " watermark: " $2 " pages"
}' /proc/zoneinfo
fi
1
2
3
4
sudo chmod +x /usr/local/bin/zram-monitor.sh

# 运行监控
sudo /usr/local/bin/zram-monitor.sh

高级优化配置

压缩算法选择

不同压缩算法的特点对比:

1
2
3
4
5
6
7
8
9
# 查看支持的压缩算法
cat /sys/block/zram0/comp_algorithm

# 常见算法特点:
# lzo: 速度快,压缩率一般,CPU占用低
# lz4: 速度很快,压缩率中等,平衡性好(推荐)
# lz4hc: 压缩率高于lz4,速度稍慢
# zstd: 压缩率高,速度中等,CPU占用较高
# lzo-rle: LZO的改进版本,对重复数据效果好

建议选择策略:

  • 内存紧张环境:选择zstd获得最高压缩率
  • 性能敏感环境:选择lz4获得最佳速度
  • 平衡需求:选择lz4hc(综合推荐)

双层Swap配置

为了避免ZRAM耗尽导致OOM,建议配置双层Swap:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 查看当前swap优先级
cat /proc/swaps

# 设置ZRAM高优先级,传统swap低优先级
# 在fstab中添加pri=1参数
sudo nano /etc/fstab

# 示例:
/swapfile none swap sw,pri=1 0 0

# 重新挂载
sudo swapoff /swapfile
sudo swapon /swapfile

# 验证优先级设置
cat /proc/swaps

内存碎片整理优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 配置内存碎片整理参数
sudo nano /etc/sysctl.conf

# 添加以下内容:
# 降低碎片整理阈值,更积极地整理内存
vm.extfrag_threshold=100

# 配置页面聚簇参数(ZRAM环境建议设为0)
vm.page_cluster=0

# 内存回收积极性(可选,谨慎使用)
vm.vfs_cache_pressure=50

# 应用配置
sudo sysctl -p

性能调优参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 在/etc/sysctl.conf中添加ZRAM优化参数

# 基础优化
vm.swappiness=80
vm.page_cluster=0

# 高级优化(根据实际情况调整)
vm.extfrag_threshold=100
vm.vfs_cache_pressure=50

# 脏页回写优化
vm.dirty_background_ratio=5
vm.dirty_ratio=10

# 应用所有配置
sudo sysctl -p

常见问题与性能分析

1. ZRAM设备创建失败

1
2
3
4
5
6
7
8
9
10
11
# 检查内核是否支持
grep CONFIG_ZRAM /boot/config-$(uname -r)

# 检查模块是否正确加载
lsmod | grep zram

# 手动加载模块
sudo modprobe zram num_devices=1

# 检查内核日志
dmesg | grep zram

2. ZRAM不被使用的问题

最常见原因:内存压力不够

ZRAM只有在系统内存压力达到一定程度时才会被使用。可以通过以下方式验证:

1
2
3
4
5
6
7
8
# 查看内存水位线
cat /proc/zoneinfo | grep -A 10 "Node 0, zone.*Normal"

# 人为制造内存压力进行测试
stress --vm 1 --vm-bytes 512M --timeout 60s

# 观察ZRAM使用情况
watch -n 1 'cat /proc/swaps && echo && free -h'

3. 压缩率不理想

1
2
3
4
5
6
7
8
9
10
11
# 查看当前压缩率
zramctl

# 分析数据类型:
# - 文本数据:压缩率通常5-10倍
# - 图片视频:压缩率较低,1.2-2倍
# - 程序代码:压缩率中等,3-5倍
# - 随机数据:几乎无法压缩

# 尝试不同压缩算法
echo zstd > /sys/block/zram0/comp_algorithm # 重启后生效

4. 系统性能下降

可能原因分析:

1
2
3
4
5
6
7
8
9
10
11
# 检查CPU使用率(压缩解压消耗CPU)
top -p $(pgrep kswapd)

# 检查ZRAM设置是否过大
# 建议:ZRAM大小 ≤ 物理内存的50%

# 检查swappiness设置是否过激进
cat /proc/sys/vm/swappiness

# 检查内存碎片情况
cat /proc/buddyinfo

性能基准对比

根据实际测试,不同存储层级的性能对比:

存储类型平均延迟相对倍数
直接内存访问~100ns
ZRAM (lz4)~3000ns30×
SSD Swap~50ms500,000×
机械硬盘 Swap~10ms100,000×

从表格可以看出,ZRAM虽然比直接内存访问慢30倍,但比传统swap快数千倍,这就是ZRAM能够有效改善系统性能的原因。

总结与最佳实践

ZRAM是一个非常实用的技术,特别适合内存受限的服务器环境。通过合理配置,可以有效提升系统的内存利用率,改善整体性能。

核心要点回顾

  1. 适用场景:内存不足但有一定压缩空间的环境
  2. 性能特点:比直接内存慢30倍,但比硬盘swap快数千倍
  3. 配置原则:ZRAM大小不超过物理内存的50%
  4. 算法选择:lz4平衡性最好,zstd压缩率最高

最佳实践建议

配置方面:

  • 使用一键脚本快速部署,手动配置深度定制
  • 设置合理的swappiness值(80-100)
  • 配置双层swap作为兜底机制
  • 选择适合工作负载的压缩算法

监控方面:

  • 定期检查压缩率和使用情况
  • 监控系统内存水位线变化
  • 关注CPU使用率变化

注意事项:

  • ZRAM并不能完全替代传统swap
  • 不同工作负载效果差异很大
  • 配置过大可能适得其反
  • 建议先在测试环境验证

现代操作系统对比

值得一提的是,内存压缩已经成为现代操作系统的标配:

  • macOS:从OS X 10.9开始默认开启
  • Windows:从Win10 TH2开始默认开启
  • Android:广泛使用ZRAM技术
  • Linux:需要手动配置,但支持最灵活

Linux的ZRAM虽然需要手动配置,但提供了最强的可定制性和透明度,这也是它在服务器环境中的优势所在。

希望这篇文章能帮到同样在为服务器内存发愁的朋友们!如果你有任何使用经验或改进建议,欢迎交流分享。

参考资料

  • 标题: 为Linux服务器开启ZRAM来节约内存
  • 作者: Kaku
  • 创建于 : 2025-08-13 21:52:58
  • 更新于 : 2025-08-13 22:03:07
  • 链接: https://www.kakunet.top/2025/08/13/为Linux服务器开启ZRAM来节约内存/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论