Alibaba Cloud Linux 3(内核版本5.10.134-14
开始)增加了Page Cache(文件缓存)限制功能,用于解决因Page Cache无限制使用带来的系统稳定性问题,例如业务抖动、预期外的内存溢出OOM(Out Of Memory)等。
背景信息
在内核系统中,系统分配内存并在相应内存子系统(memcg)中的统计达到memcg设定的内存上限时,会触发memcg级别的直接内存回收,这可能导致当前进程的性能抖动。尽管具有Memcg后台异步回收功能,但对于突发性的内存申请来说,其效果有限。有些任务例如Spark计算框架,Page Cache会经常占用大量内存,并且大部分是脏页。脏页的回收速度较慢,导致了预期外的OOM情况的发生。因此,限制Page Cache的使用量对于保持业务的稳定性和减少预期外的OOM问题非常重要。
Alibaba Cloud Linux 3增加了Page Cache限制功能,支持以memcg为粒度(包括根组即整机)对Page Cache的使用进行限制。该功能可以通过设置Page Cache的上限,对超过限制的Page Cache进行异步回收或者同步回收。这可以帮助控制Page Cache的使用量,防止其占用过多的内存资源,从而提高系统的稳定性和可靠性。
接口说明
接口 | 说明 |
/sys/kernel/mm/pagecache_limit/enabled | 该接口是全局开关,用于设置当前内核系统是否启用Page Cache限制功能。取值范围:0~1,默认值为0。
|
/sys/fs/cgroup/memory/<memcg目录名称>/memory.pagecache_limit.enable | 该接口是memcg开关,用于设置各memcg是否启用Page Cache限制功能。取值范围:0~1,默认值为0。
|
/sys/fs/cgroup/memory/<memcg目录名称>/memory.pagecache_limit.size | 该接口限制当前memcg的Page Cache使用量(单位:字节)。取值范围:0~当前memcg的
|
/sys/fs/cgroup/memory/<memcg目录名称>/memory.pagecache_limit.sync | 该接口控制当前memcg的Page Cache使用量超出限制后,采用异步回收还是同步回收。取值范围:0~1,默认值为0。
|
工作原理
开启Page Cache限制功能后,memcg粒度的工作原理如下。
当memcg进程分配Page Cache时,判断当前memcg的Page Cache是否超过限制,并从当前memcg开始往上遍历,逐级检查父memcg的
memory.pagecache_limit
值,如果该值为0,表示父memcg禁用了Page Cache限制,则当前memcg以及其子memcg不会受到Page Cache的限制。当memcg的Page Cache使用超过限制时,根据
memory.pagecache_limit.sync
判断当前回收采用同步回收还是异步回收。开始回收Page Cache。
同步回收:默认仅支持未映射文件页回收,当扫描次数超过4次时,允许对映射文件页进行回收。
异步回收:默认支持未映射文件页和映射文件页回收,当扫描次数超过2次时,允许对脏页进行回收。
说明在内存管理中,存在以下不同类型的页。
未映射文件页:这些页是指未被映射到任何文件的内存页。通常用于临时数据和进程私有的内存区域,不会持久化到磁盘上。
映射文件页:这些页是指被映射到文件的内存页。映射文件页允许进程通过访问内存的方式来读取和写入文件数据,从而实现了文件的随机访问。
脏页:脏页是指映射文件页中已经被修改过的页。当进程对映射文件页进行写入时,相应的页会被标记为脏页。这表示文件在内存中的副本已经与磁盘上的文件内容不一致。脏页通常会定期地被写回磁盘,以确保数据的持久性。
接口配置示例
本示例的场景是构造20 MiB大小的Page Cache,并限制Page Cache的使用量为10 MiB。开启Page Cache限制功能后,测试是否符合预期。
远程登录ECS实例。
具体操作,请参见通过密码或密钥认证登录Linux实例。
运行以下命令,打开Page Cache限制功能的全局开关。
sudo sh -c 'echo 1 > /sys/kernel/mm/pagecache_limit/enabled'
启用Page Cache限制功能并限制Page Cache的使用量。
运行以下命令,创建一个memcg目录,例如
/sys/fs/cgroup/memory/test/
。sudo mkdir -p /sys/fs/cgroup/memory/test/
运行以下命令,设置memcg的Page Cache使用量。
本示例限制memcg的Page Cache使用量为10485760字节(约10 MiB),命令为:
sudo sh -c 'echo 10485760 > /sys/fs/cgroup/memory/test/memory.pagecache_limit.size'
运行以下命令,设置一种回收方式。
异步回收
sudo sh -c 'echo 0 > /sys/fs/cgroup/memory/test/memory.pagecache_limit.sync'
同步回收
sudo sh -c 'echo 1 > /sys/fs/cgroup/memory/test/memory.pagecache_limit.sync'
运行以下命令,启用memcg的Page Cache限制功能。
sudo sh -c 'echo 1 > /sys/fs/cgroup/memory/test/memory.pagecache_limit.enable'
构造Page Cache。
(条件必选)运行以下命令,安装
libcgroup
软件包。构造Page Cache需要使用
cgexec
命令。cgexec
命令通常与libcgroup软件包一起提供,并且需要在系统上进行安装。如果您的系统中没有cgexec
,请先安装libcgroup软件包。sudo yum install libcgroup-tools
运行以下命令,构造Page Cache。
本示例使用
dd
命令以每次写入1 MiB的块大小,连续写入20次,来构造一个总计20 MiB的Page Cache。命令为:sudo dd if=/dev/zero of=./testfile bs=1M count=20 oflag=direct sudo cgexec -g "memory:test" cat ./testfile > /dev/null
查看是否符合预期。
运行以下命令,查看当前Page Cache的使用量。
grep cache /sys/fs/cgroup/memory/test/memory.stat
返回结果如下:
在返回结果中,
cache
表示当前Page Cache的使用量为10543104字节(约10 MiB),说明已成功限制。运行以下命令,查看Page Cache限制功能的回收结果。
cat /sys/fs/cgroup/memory/test/memory.exstat
返回结果如下:
在返回结果中,
pagecache_limit_reclaimed_kb
表示回收的页数(单位:千字节),这里是10108千字节(约10 MiB),说明回收了10 MiB。通过测试结果可以看出,构造了20 MiB的Page Cache,限制Page Cache的使用量为10 MiB。当Page Cache的使用量超出限制时,回收了10 MiB的Page Cache,符合预期。
说明如果测试发现
pagecache_limit_reclaimed_kb
值较大不符合预期,可能是IO预读引入的问题导致额外的回收。此时建议您运行echo 128 | sudo tee /sys/block/vda/queue/read_ahead_kb
命令(vda
是云盘的设备名称,请您根据实际环境替换),设置IO预读量,然后重新测试。