Page Cache限制功能

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。

  • 取值为1,表示允许启用Page Cache限制功能。

  • 取值为0,表示禁用全部Page Cache限制功能。

/sys/fs/cgroup/memory/<memcg目录名称>/memory.pagecache_limit.enable

该接口是memcg开关,用于设置各memcg是否启用Page Cache限制功能。取值范围:0~1,默认值为0。

  • 取值为1,表示当前memcg启用Page Cache限制功能。

  • 取值为0,表示当前memcg禁用Page Cache限制功能,则该memcg以及其子memcg不会受到Page Cache的限制。

/sys/fs/cgroup/memory/<memcg目录名称>/memory.pagecache_limit.size

该接口限制当前memcg的Page Cache使用量(单位:字节)。取值范围:0~当前memcg的memory.limit_in_bytes值,由您自定义设置,默认值为0。

  • 取值为0,表示当前memcg禁用Page Cache限制功能(即使全局开关和memcg开关都打开)。

  • 取值为非0值,表示当前memcg tree的Page Cache的使用量的上限。

    说明

    memcg的Page Cache使用量包含当前memcg的所有子memcg的使用量。

/sys/fs/cgroup/memory/<memcg目录名称>/memory.pagecache_limit.sync

该接口控制当前memcg的Page Cache使用量超出限制后,采用异步回收还是同步回收。取值范围:0~1,默认值为0。

  • 取值为0,表示采用异步回收。异步回收采用workqueue的方式实现,在后台以异步的方式进行回收操作,可以减少对主线程的影响。

    说明

    workqueue是Linux内核中的一种机制,用于管理和执行异步工作(即后台任务)。通过将回收操作添加到workqueue中,系统可以将回收任务交给后台线程处理,从而实现异步回收。

  • 取值为1,表示采用同步回收。同步回收会阻塞当前进程进行直接回收,即回收操作会在当前进程的上下文中执行,可能会导致当前进程的性能抖动。

工作原理

开启Page Cache限制功能后,memcg粒度的工作原理如下。

  1. 当memcg进程分配Page Cache时,判断当前memcg的Page Cache是否超过限制,并从当前memcg开始往上遍历,逐级检查父memcg的memory.pagecache_limit值,如果该值为0,表示父memcg禁用了Page Cache限制,则当前memcg以及其子memcg不会受到Page Cache的限制。

  2. 当memcg的Page Cache使用超过限制时,根据memory.pagecache_limit.sync判断当前回收采用同步回收还是异步回收。

  3. 开始回收Page Cache。

    • 同步回收:默认仅支持未映射文件页回收,当扫描次数超过4次时,允许对映射文件页进行回收。

    • 异步回收:默认支持未映射文件页和映射文件页回收,当扫描次数超过2次时,允许对脏页进行回收。

      说明

      在内存管理中,存在以下不同类型的页。

      • 未映射文件页:这些页是指未被映射到任何文件的内存页。通常用于临时数据和进程私有的内存区域,不会持久化到磁盘上。

      • 映射文件页:这些页是指被映射到文件的内存页。映射文件页允许进程通过访问内存的方式来读取和写入文件数据,从而实现了文件的随机访问。

      • 脏页:脏页是指映射文件页中已经被修改过的页。当进程对映射文件页进行写入时,相应的页会被标记为脏页。这表示文件在内存中的副本已经与磁盘上的文件内容不一致。脏页通常会定期地被写回磁盘,以确保数据的持久性。

image

接口配置示例

本示例的场景是构造20 MiB大小的Page Cache,并限制Page Cache的使用量为10 MiB。开启Page Cache限制功能后,测试是否符合预期。

  1. 远程登录ECS实例。

    具体操作,请参见通过密码或密钥认证登录Linux实例

  2. 运行以下命令,打开Page Cache限制功能的全局开关。

    sudo sh -c 'echo 1 > /sys/kernel/mm/pagecache_limit/enabled'
  3. 启用Page Cache限制功能并限制Page Cache的使用量。

    1. 运行以下命令,创建一个memcg目录,例如/sys/fs/cgroup/memory/test/

      sudo mkdir -p /sys/fs/cgroup/memory/test/
    2. 运行以下命令,设置memcg的Page Cache使用量。

      本示例限制memcg的Page Cache使用量为10485760字节(约10 MiB),命令为:

      sudo sh -c 'echo 10485760 > /sys/fs/cgroup/memory/test/memory.pagecache_limit.size'
    3. 运行以下命令,设置一种回收方式。

      • 异步回收

        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'
    4. 运行以下命令,启用memcg的Page Cache限制功能。

      sudo sh -c 'echo 1 > /sys/fs/cgroup/memory/test/memory.pagecache_limit.enable'
  4. 构造Page Cache。

    1. (条件必选)运行以下命令,安装libcgroup软件包。

      构造Page Cache需要使用cgexec命令。cgexec命令通常与libcgroup软件包一起提供,并且需要在系统上进行安装。如果您的系统中没有cgexec,请先安装libcgroup软件包。

      sudo yum install libcgroup-tools
    2. 运行以下命令,构造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
  5. 查看是否符合预期。

    1. 运行以下命令,查看当前Page Cache的使用量。

      grep cache /sys/fs/cgroup/memory/test/memory.stat

      返回结果如下:

      image.png

      在返回结果中,cache表示当前Page Cache的使用量为10543104字节(约10 MiB),说明已成功限制。

    2. 运行以下命令,查看Page Cache限制功能的回收结果。

      cat /sys/fs/cgroup/memory/test/memory.exstat

      返回结果如下:

      image.png

      在返回结果中,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预读量,然后重新测试。