2 核 2G 云服务器配置 ZRAM:从 vm.swappiness=0 开始
我以前买过一台 2 核 2G 的 Linux 云服务器。系统装好以后,我检查内存参数,发现 vm.swappiness 是 0:
sysctl vm.swappinessvm.swappiness = 0这是当时那台实例和系统镜像的实测结果,不代表所有云厂商的当前镜像都采用相同默认值。新机器仍然应该先检查,别照着旧经验直接修改。
2G 内存很容易碰到边界。服务平时可能只占一半,更新依赖、构建项目或者几个容器同时活跃时,剩余内存很快就没了。我做的第一项系统调整就是启用 /dev/zram0,随后把 swappiness 改成 90,再准备一个磁盘 swapfile 兜底。
这台机器后来用了很多年。我在上面反复搭建和拆掉过各种个人服务,2 核 CPU 不快,2G 内存也从来不宽裕,但这套配置一直保留着。回头看,ZRAM 是我使用小规格个人云服务器时最有用的一项配置。
我对这种默认值的看法
我的判断很直接:小规格实例把 swappiness 设成 0,是一项对销售更高内存配置有利的默认设置。
2G 内存顶住以后,服务变慢、进程被 OOM 杀掉,用户最容易得出的结论就是“这台机器内存不够”,然后从 2G 升到 4G。可系统明明支持压缩内存,厂商却没有默认启用 zram,还把 Swap 的介入时间推到很晚。站在购买者的角度,我很难把这只看成一次无关商业利益的技术选择。
当然,swappiness=0 也有技术上的理由:传统磁盘 Swap 可能造成明显延迟,云厂商无法预先知道每个用户运行什么负载。只是它带来的商业效果同样明显,小规格实例更快显得不够用,升级套餐成了最省事的答案。
我没有云厂商的内部设计资料,不能证明这项默认值就是销售部门要求的。这里记录的是我用了多年小规格服务器以后形成的观点,不是已经得到厂商确认的产品策略。
swappiness=0 不等于禁止 Swap
我当年第一次看到 0,理解成了“即使有交换空间,系统也不使用”。这个说法不准确。
Linux 内核的 swappiness 文档说明,这个参数用于表示交换 I/O 与文件系统分页 I/O 的相对成本,范围是 0~200。数值越低,内核越不愿意交换匿名页;设为 0 时,内核会把主动换页推迟到空闲页和文件页已经低于水位线以后。
所以,0 不是关闭 Swap。它只是让 Swap 很晚才介入。对于只有 2G 内存的服务器,这通常意味着冷页长时间留在物理内存,真正顶到边界时才突然回收或换页。
ZRAM 的情况不同。它把交换页压缩后保存在内存里,没有磁盘随机 I/O。内核文档也专门提到,zram、zswap 这类内存交换可以考虑更高的 swappiness。具体值仍然取决于负载,我多年使用的值是 90,并没有把它写成所有机器都必须采用的标准答案。
配置前先留下基线
free -h
swapon --show
sysctl vm.swappiness
df -h /如果 swapon --show 没有输出,说明当前没有启用交换设备。如果已经有 swapfile 或云镜像自带的交换分区,先记下它的路径、容量和优先级,不要直接覆盖。
安装 systemd-zram-generator
我使用的是提供 apt 的 Debian/Ubuntu 系统:
sudo apt update
sudo apt install systemd-zram-generator
sudoedit /etc/systemd/zram-generator.conf写入下面的配置:
[zram0]
zram-size = ram / 2
compression-algorithm = lzo-rle
swap-priority = 1002G 物理内存对应约 1G 的 zram 逻辑容量。zram-size 不是启动后立即划走 1G 内存,只有实际写入交换页时才会消耗内存,而且消耗量取决于数据压缩率。
systemd-zram-generator 的配置说明建议把比例放在 0.1~0.5 之间,默认值也是 min(ram / 2, 4096)。它的 swap-priority 默认就是 100,我仍然把它明确写出来,方便以后检查 zram 与磁盘 swap 的顺序。
配置完成后重新加载 systemd,并启动生成的交换单元:
sudo systemctl daemon-reload
sudo systemctl start dev-zram0.swap如果当前发行版没有立即生成这个单元,重启一次再检查:
sudo reboot把 swappiness 从 0 改成 90
不要同时在 /etc/sysctl.conf 和多个 /etc/sysctl.d/*.conf 文件里重复设置。新建一个用途明确的配置文件即可:
sudoedit /etc/sysctl.d/99-zram.confvm.swappiness = 90加载并确认:
sudo sysctl --system
sysctl vm.swappiness调整 swappiness 决定内核多积极地考虑换页,交换优先级则决定已经需要换页时先用哪个设备。这是两个不同的开关。这里让 zram 使用优先级 100,稍后创建的磁盘 swapfile 使用 99,系统会优先选择 /dev/zram0。
创建磁盘 swapfile 兜底
ZRAM 仍然消耗物理内存,而且遇到难以压缩的数据时收益会下降。我还会创建一个 4 GiB 的磁盘 swapfile,用来接住 zram 容量之外的页面:
sudo dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progress
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon --priority 99 /swapfile确认启用成功后,再写入 /etc/fstab:
grep -qE '^[[:space:]]*/swapfile[[:space:]]+' /etc/fstab || \
echo '/swapfile none swap defaults,pri=99 0 0' | sudo tee -a /etc/fstab
sudo findmnt --verify这里的 4 GiB 是我当年的实际选择,不是按照 2G 内存机械推导出来的比例。磁盘很小、写入寿命敏感或者业务不允许明显换页延迟时,需要重新决定是否创建以及创建多大。
验证最终状态
free -h
swapon --show
zramctl
sysctl vm.swappiness
systemctl status dev-zram0.swap --no-pager我希望看到的是 /dev/zram0 优先级 100、/swapfile 优先级 99,以及:
vm.swappiness = 90swapon --show 中 zram 的 USED 是压缩前的逻辑交换量。要看它真正消耗了多少物理内存,应检查 zramctl 的 COMPR 和 TOTAL。例如 DATA 为 3G、TOTAL 约 1G,表示约 3G 原始页经过压缩后,连同管理开销实际占用了约 1G 内存,并不是 zram 又额外占了 3G。
我踩过的几个坑
不要同时安装并启用 systemd-zram-generator 和 zram-tools。两套工具都想管理 /dev/zram0,最后看到的设备、单元和配置来源会变得很难判断。
swappiness 也不是越高越好。ZRAM 用 CPU 换内存,CPU 本来就很紧张或者数据几乎无法压缩时,高频换页可能适得其反。我的 2 核 2G 服务器适合 90,是长期使用后的个人配置,不是一次跑分得出的通用最优值。
最后,Swap 和 ZRAM 都不能修复内存泄漏。它们提供的是余量,让短时峰值不至于马上杀进程。某个服务长期增长,还是要找出进程、限制容器内存或者升级规格。
删除磁盘 swapfile 时要先看内存
如果以后不再需要磁盘 swapfile,先确认物理内存和 zram 能接住当前已交换的数据:
free -h
swapon --show确认余量足够后再执行:
sudo swapoff /swapfile
sudoedit /etc/fstab
sudo rm /swapfile
swapon --show内存已经很紧张时直接 swapoff,系统必须把交换页重新搬回内存,可能卡住甚至触发 OOM。这个清理动作不应该在业务高峰时做。
我后来配置新的小规格服务器,仍然会先检查 swappiness 和现有 Swap,再决定 zram 大小。机器只有 2G 内存时,这几分钟配置带来的余量,比安装一堆所谓优化脚本更实在。