之前,我们研究了交换空间如何严重降低 Linux 性能。然后我们调整 Linux 内核参数以更好地使用服务器内存并避免频繁使用交换空间。
该话题,我们在教程中提到,可以阅读我们之前编写的教程:Linux 性能:为什么你应该添加交换空间。
由于在微信公众号,一位用户的评论提到在USB设备使用交换空间反而会更慢,应该使用 zRAM,现在我们来聊聊 zRAM 与交换空间。
什么是 ZRAM
zram 也称为 zRAM,先前称为compcache。是Linux 内核的核心功能,可提供虚拟内存压缩。
zram 通过在 RAM 内的压缩块设备的分页,直到必须使用硬盘的交换空间,避免在磁盘进行分页,从而提高性能。
由于 zram 可以用内存代替硬盘为系统提供交换空间的功能,zRAM 可以在内核需要交换/分页时,让Linux 更好利用RAM。
zRAM 的一个缺点是它使用一些 CPU 进行压缩,但 zRAM 在磁盘IO与压缩内存后所获得的收益所抵消。
为什么仍然使用交换空间 SWAP
交换空间在 Linux 系统很有用,即使仍有可用的 RAM。Linux 内核会将几乎不使用的内存页移动到交换空间,以确保内存中有更多空间可用于更频繁使用的内存页。
在最近的内核中,交换算法已经过全面修改,开始考虑文件支持和匿名(非文件支持)内存的活动和非活动内存。
只有当内核被迫不断地将内存页面移入和移出内存并进行交换时,交换IO才会成为性能问题。
为什么使用 zRAM
vfs_cache_pressure 控制内核回收内存缓存和 inode 对象的频率。vfs_cache_pressure 默认值是100,通常建议值范围是 50 到 500。
较高的 vfs_cache_pressure 值会使内核更快的回收内存缓存,这可能会带来一点性能的损失,但比不上使用交换空间带来的性能损失。
较低的 vfs_cache_pressure 值会使内核更喜欢保留内存缓存,这会容易导致内存不足,因此你可能需要增加更多的RAM。
swappiness 控制内核使用交换空间频率。Swappiness 的值介于 0 和 100 之间,默认值为 60。
较低的 Swappiness 值会使内核减少交换空间的使用。较高的值会使内核优先使用交换空间。在足够内存系统上,设置 swappiness 较低的值可以提高系统的响应能力。
如果你的系统内存不足,则可以尝试调整 swappiness 和 vfs_cache_pressure 的值,使用 vim 编辑文件 /etc/sysctl.conf。
sudo vim /etc/sysctl.conf
vm.swappiness=10
vm.vfs_cache_pressure=500
这将会增加缓存压力,似乎有点适得其反,因为内存缓存对性能很有帮助。但是,过于频繁的交换空间会显着降低服务器的整体性能。
因此,不在内存保留尽可能多的缓存,有助于降低内存的使用,从而减少交换空间使用。此外,将 vm.swappiness 低至 1,内核将会大幅度减少使用交换空间。
那么有没有一种办法在尽量保留多的内存缓存,但我们仍然希望减少使用交换空间,避免使用交换空间增加磁盘的 I/O,大幅度降低性能。这个时候我们就可以考虑使用 zRAM。
开启 zRAM
zRAM 模块由 Systemd 控制,因此不需要 fstab 进行自动挂载。由于一切都已经开箱即用,我们只需要创建几个文件并修改其中一个文件。
zRAM是 Linux 内核的模块,因此,我们需要在模块 /etc/modules-load.d/ 添加zram.conf 文件启用 zRAM 模块。
除了启用 zRAM 模块还需要配置 zRAM 模块参数,创建文件 /etc/modprobe.d/zram.conf。
options zram num_devices=1 表示创建一个设备文件,该文件将会保存在设备目录,文件名称是 /dev/zram0。
如果 num_devices 的数值不等于1,内核将会创建多个 zram 文件/dev/zram{0,1,2,3...}。并且你的 udev 规则文件也需要创建多个。
最后创建 udev 规则文件,使用 Linux 内核设备管理器 udev 在系统启动时创建 zRAM 设备文件。
echo "zram" | sudo tee -a /etc/modules-load.d/zram.conf
echo "options zram num_devices=1" | sudo tee -a /etc/modprobe.d/zram.conf
echo 'KERNEL=="zram0", ATTR{disksize}="512M",TAG+="systemd"' | sudo tee -a /etc/udev/rules.d/99-zram.rules
现在已经在内核启用 zRAM 模块,接下来创建 SystemD 单元文件,在系统启动时自动打开 zRAM 文件并作为交换空间挂载。
如果你系统已经存在交换空间,那么总的交换空间的大小是zRAM的大小加交换空间的大小。
sudo vim /etc/systemd/system/zram.service
sudo systemctl enable zram
[Unit]
Description=Swap with zram
After=multi-user.target
[Service]
Type=oneshot
RemainAfterExit=true
ExecStartPre=/sbin/mkswap /dev/zram0
ExecStart=/sbin/swapon /dev/zram0
ExecStop=/sbin/swapoff /dev/zram0
[Install]
WantedBy=multi-user.target
zRAM 缓存压力 与交换空间
对于缓存压力较大的服务器,也就是低内存设备,可以在使用 ZRAM 时,增加缓存压力,使内核尽可能回收内存。
sudo vim /etc/sysctl.conf
vm.vfs_cache_pressure=500
vm.swappiness=100
vm.dirty_background_ratio=1
vm.dirty_ratio=50
vm.vfs_cache_pressure=500 增加内存缓存压力,这将会增加内核回收内存缓存的趋势。更快的回收内存缺点抵消使用交换空间带来的性能损失。
vm.swappiness=100 现在我们已经增加 ZRAM 优先代替交换空间,因此这里,我们增加内核交换内存页面的积极程度。
vm.dirty_background_ratio=1 当后台脏内存页面超过 1% 时,开始写入磁盘。Dirty是指数据存储在Page Cache,但这些数据需要优先写入存储设备。
vm.dirty_ratio=50 当后台脏内存页面超过 50% 时,所有写入磁盘的脏页面都会被阻塞,直到写完所有为止。
设置这四行,当与 ZRAM 一起使用时,将有助于在最终需要的内存总量超过已安装内存总量的情况下提高性能。
ZRAM 使交换成本更低,并且可以存储压缩的数据比之前数据小 2 到 3 倍,也许你现在就应该添加zRAM。
随着时间的推移,即使使用了大部分已安装的内存,内核也可以在CPU不繁忙时更快地交换到 ZRAM,使CPU 和交换 I/O 不会延迟到所有时间。
最后,为了避免OOM以及预留更多的响应时间,作为最后的手段,你可以选择保留一点交换空间。
在同时使用 zRAM 和 交换空间时,需要注意的是 zRAM 和 交换空间的优先级,优先级别越高,则优先使用。
直到优先级较高的用完后,才开始使用交换空间。优先级的设置可以使用 swapon 命令的 -p / --priority 选项进行设置。
sudo cat /proc/swaps
Filename Type Size Used Priority
/swapfile file 511996 0 -1
/dev/zram0 partition 2097144 399320 5
对于缓存压力较小的服务器,您可以在使用 ZRAM 时,降低缓存的压力,也就是降低内核回收内存的频率,将缓存数据保留更长时间。
sudo vim /etc/sysctl.conf
vm.vfs_cache_pressure=50
vm.swappiness=10
vm.dirty_background_ratio=1
vm.dirty_ratio=20
结论
使用 ZRAM,尤其是在低内存设备中,对于在 Linux 服务器已经过多使用 RAM 时 非常有用。
1GB 的 ZRAM 可在压缩后存储大约 2 到 3 GB的数据。此外,建议优先使内核更频繁地交换到 ZRAM。
此外,使用 zRAM 除了提高系统性能之外,还有一个好处是可以延长 SSD 固态硬盘的寿命。