系统相关
首页 > 系统相关> > 《Linux内核技术实战课》总结一:PageCache

《Linux内核技术实战课》总结一:PageCache

作者:互联网

总览

Page Cache:内核管理的内存

场景:服务器的 load 飙高; 服务器的 I/O 吞吐飙高; 业务响应时延出现大的毛刺; 业务平均访问时延明显增加

应用程序产生Page Cache的逻辑示意图,是在应用程序读写文件的过程中产生的
在这里插入图片描述

产生,即被分配:有两种方式
1 标准 I/O 是写的 (write) 用户缓冲区 (Userpace Page 对应的内存),然后再将用户缓冲区里的数据拷贝到内核缓冲区 (Pagecache Page 对应的内存);如果是读的 (read) 话则 是先从内核缓冲区拷贝到用户缓冲区,再从用户缓冲区读数据,也就是 buffer 和文件内容不存在任何映射关系
2 存储映射 I/O 而言是直接将 Pagecache Page 给映射到用户地址空间,用户直接读写 Pagecache Page 中内容。
在这里插入图片描述
产生例子:首先往用户缓冲区 buffer( Userspace Page) 写入数据, 然后 buffer 中的数据拷贝到内核缓冲区(Pagecache Page),如果内核缓冲区中还没有这个 Page,就会发生 Page Fault 会去分配一个 Page,拷贝结束后该 Pagecache Page 是一个 Dirty Page(脏页),然后该 Dirty Page 中的内容会同步到磁盘,同步到磁盘后,该 Pagecache Page 变为 Clean Page 并且继续存在系统中
在这里插入图片描述

死亡,即被回收:应用在申请内存的时候,即使没有 free 内存,只要还有足够可回收的 Page Cache,就可以通过回收 Page Cache 的方式来申请到内存;回收的方式主要是两种:直接回收和后台回收,可以使用sar -B 1命令 或者 /proc/vmstat 来观察
在这里插入图片描述

问题排查:Linux 内核主要是通过 /proc 和 /sys 把系统信息导出给用户, 可以去这两个目录下读取一下系统信息,看看哪些指标异常

处理Page Cache难以回收产生的load飙高问题

总体思路是提前回收、加强回收能力

直接内存回收是在进程申请内存的过程中同步进行的回收,而这个回收过程可能会消 、耗很多时间,进而导致进程的后续行为都被迫等待,这样就会造成很长时间的延迟,以及 系统的 CPU 利用率会升高,最终引起 load 飙高;
在开始内存回收后,首先进行后台异步回收(蓝色标记的地 方),这不会引起进程的延迟;如果后台异步回收跟不上进行内存申请的速度,就会开始同步阻塞回收,导致延迟(红色和粉色标记的地方,这就是引起 load 高的地址):
在这里插入图片描述

解决方案:及早地触发后台回收来避免应用程序进行直接内存回收,通过调高min_free_kbytes参数即可

直接回收过程中,如果存在较多脏页就可能涉及在回收过程中进行回写,这可能会造成非常大的延迟,而且因为这个过程本身是阻塞式的,所以又可能进一步导致系统中处于 D 状态的进程数增多,最终的表现就是系统的 load 值很高;
如果系统中既有快速 I/O 设备,又有慢速 I/O 设备(比如图中的 ceph RBD 设备,或者其他慢速存储设备比如 HDD),直接内存回收过程中遇到了正在往慢速 I/O 设备 回写的 page,就可能导致非常大的延迟:
在这里插入图片描述

解决方案:控制好系统中积压的脏页数据,可以通过 sar -r 来观察系统中的脏页个数

系统中如果还有一半左右的 free 内存,但还是频频触发 direct reclaim(直接回收),导致业务抖动得比较厉害,那么可以先看看是否设置了 zone_reclaim_mode,是的话可以先设置为0

可以利用 linux 的 tracepoint 来有效地衡量业务延迟问题是否由 zone reclaim 引起的、它引起的延迟究竟有多大

处理Page Cache容易回收引起的业务性能问题

总体思路:保护重点数据

drop_cache导致:比如执行2,虽然只想清掉slab,但是因为清掉了inode,会导致无法通过inode去PageCache去查询文件(因为如果 inode 被回收的话,那么它对应的 Page Cache 也都会被回收掉)
在这里插入图片描述

可以通过 grep drop /proc/vmstat来查看drop操作的执行情况

内存回收图:Reclaimer 是指回收者,它可以是内核线程(包括 kswapd) 也可以是用户线程;
回收的时候,它会依次来扫描 pagecache page 和 slab page 中有哪 些可以被回收的,如果有的话就会尝试去回收,如果没有的话就跳过。在扫描可回收 page 的过程中回收者一开始扫描的较少,然后逐渐增加扫描比例直至全部都被扫描完:
在这里插入图片描述

Reclaim Slab容易出“误操作”里描述的问题,可以通过grep inodesteal /proc/vmstat来查看回收的过程中,因为回收 inode 而释放的 pagecache page 个数

解决方案:
1 从应用代码层面来优化:可以明确地来对读写文件过程中产生的 Page Cache 区 别对待;比如说,对于重要的数据,可以通过 mlock来保护它,防止被回收以及被 drop(可通过egrep “Unevictable|Mlocked” /proc/meminfo来观察);对于不重要的数据(比如日志),那可以通过 madvise告诉内核来立即释放这 些 Page Cache
2 从系统层面来调整:在有些情况下,对应用程序而言,修改源码是件比较麻烦的事,Linux 内核实现了不改应用程序的源码而从系统层面调整来保护重要数据的机制,叫做memory cgroup protection,其原理就是将需要保护的应用程序使用 memory cgroup 来保护起来,这样该应用 程序读写文件过程中所产生的 Page Cache 就会被保护起来不被回收或者最后被回收
在这里插入图片描述

判断问题是否由PageCache引起

问题分析总思路:
在这里插入图片描述

除了Page Cache,还可能是锁冲突太厉害、物理资源(CPU、内存、磁 盘 I/O、网络 I/O)有争抢、内核特性设计缺陷等等导致的

首先使用 sar 来采集 Page Cache 的概况,其PSI信息的 avg10 一列表示最近 10s 内存的平均压力情况,如果它很大(比如 大于 40)那 load 飙高大概率是由于内存压力,尤其是 Page Cache 的压力引起的

接下来需要知道是什么行为导致PageCache压力大,也就是看看以下指标是否有异常:
在这里插入图片描述

除此之外,有时候还需要知道是什么东西在进行连续内存的申请,可以通过tracepoint来分析:
在这里插入图片描述

可以根据 sar 的日志信息来判断当时发生了什么事情

标签:load,Cache,回收,内核,Linux,PageCache,Page,内存
来源: https://blog.csdn.net/qq_41594698/article/details/111058631