暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Linux PageCache详解与性能调优

大数据从业者 2021-06-30
5970

前言

Linux系统经常出现空闲内存少,如同内存不够用一样。其实这是Linux系统内存管理的一个优秀特性:Linux尽量充分利用系统内存。比如:将被访问过的硬盘数据加载到内存(buffer/Cache),利用内存高速读写的特性来提供Linux系统高效率的数据访问能力。



Page Cache概述

应用程序读取Linux文件的两种方式:read、mmap。无论哪种,Linux内核都会相应申请一块Page cache用来缓存文件内容。后续再次读取就直接从Page cache获取,不用访问磁盘文件,以此来提升Linux系统性能。

Linux系统的PageCache通过free命令查看,如图:

    cache :表示已读取的数据(快取)
    buffer:表示要写入的数据 (缓存)
    复制


    概念上的差别:cache是针对文件的,buffer是针对磁盘块数据的。



    Page Cache的意义

    实际案例测试:

    首先,提前生成一个大小为4G的文件;测试文件的读取耗时;然后清空Page cache,再次测试文件的读取耗时,两者耗时对比。

    1.  生成一个大小为4G的文件

      [root@felixzh home]# dd if=/dev/zero of=/home/felixzh_dd.out bs=4096 count=1048576 status=progress
      复制

      2. 测试文件的读取耗时:

        [root@felixzh home]# time cat home/felixzh_dd.out &> dev/null
        复制

        3. 清空Page Cache

          [root@felixzh home]# sync && echo 3 > proc/sys/vm/drop_caches
          复制

          4. 再次测试文件读取文件的耗时:

          测试结果表明:第一次耗时远小于第二次;原因是生成文件时,已经缓存在cache。第一次读取的是内存数据。清空cache后,再次读取则是从磁盘上读取。所以Page Cache存在的意义:减小磁盘I/O,提升应用I/O速度。


          Page Cache的产生

          两种方式:

            Buffered I/O(标准I/O)
            Memory-Mapped I/O(储存映射IO)
            复制

            1. 存储映射I/O直接将Page映射到用户空间,用户直接读写PageCache。

            2. 标准I/O首先写用户缓存区(User page),然后再将用户缓存区里的数据拷贝到内核缓存区(Pagecahe Page)。类似的,读操作先将内核缓存区拷贝到用户缓存区,然后从用户缓存区读取数据。

            所以说,存储映射I/O要比标准的I/O效率高一些,毕竟少了“用户空间到内核空间互相拷贝”的过程。

            下图简单描述标准I/O写操作流程:

            Linux系统提供了脏页同步到磁盘的相关参数:

              [root@felixzh home]#  cat proc/vmstat | egrep "dirty|writeback"
              复制

              其中:

                nr_dirty     #表示系统中脏页数量(单位为Page 4KB)
                nr_writeback #表示正在回写到磁盘的脏页数量(单位为Page 4KB)
                复制





                Page Cache的死亡

                上面提到的使用free命令,查看到的buffer/cache,表示“活着”的Page Cache。什么时候回收呢?两种触发方式:后台回收、直接回收。

                借助sar工具可以很直观的观察Page cache的回收行为:

                  pgscank/s:kswapd(后台回收线程)每秒扫面的Page个数
                  pgscand/s:Application在内存申请过程中每秒直接扫描的Page个数
                  pgsteal/s:扫面的page中每秒被回收的个数
                  %vmeff:pgsteal/(pgscank+pgscand),回收效率,越接近100说明系统越安全,越接近0,说明系统内存压力越大
                  pgpgin/s 表示每秒从磁盘或SWAP置换到内存的字节数(KB)
                  pgpgout/s: 表示每秒从内存置换到磁盘或SWAP的字节数(KB)
                  fault/s: 每秒钟系统产生的缺页数,即主缺页与次缺页之和(major + minor)
                  majflt/s: 每秒钟产生的主缺页数.
                  pgfree/s: 每秒被放入空闲队列中的页个数
                  复制







                  性能调优

                  Linux提供影响脏页数据回写的相关参数:

                    [root@felixzh home]# sysctl -a | grep dirty
                    复制

                      vm.dirty_background_ratio    触发回刷的脏数据占用内存的百分比         
                      vm.dirty_background_bytes    触发回刷的脏数据量                     
                      vm.dirty_bytes               触发同步写的脏数据量                    
                      vm.dirty_ratio               触发同步写的脏数据占可用内存的百分比      
                      vm.dirty_expire_centisecs    脏数据超时回刷时间(单位:1/100S)       
                      vm.dirty_writeback_centisecs 回刷进程定时唤醒时间
                      复制

                      如果dirty_ratio大于dirty_background_ratio,是不是就不会达到dirty_ratio呢?首先达到dirty_background_ratio条件,会触发flush进程进行异步的回写操作,此时应用进程仍然可以进行写操作,如果应用进程写入量大于flush进程刷出量。那自然就会达到vm.dirty_ratio这个参数所设定的阙值,此时操作系统会转入同步地进行脏页的过程,阻塞应用进程。



                      配置实例

                      场景1:尽可能不丢数据


                        dirty_background_ratio = 5
                        dirty_ratio = 10
                        dirty_writeback_centisecs = 50
                        dirty_expire_centisecs = 100
                        复制


                        此配置通过减少Cache,更加频繁唤醒回刷进程的方式,尽可能让数据回刷。

                        场景2:追求更高性能


                          dirty_background_ratio = 50
                          dirty_ratio = 80
                          dirty_writeback_centisecs = 2000
                          dirty_expire_centisecs = 12000
                          复制


                          此配置通过增大Cache,延迟回刷唤醒时间来尽可能缓存更多数据,进而实现提高性能。

                          场景3:突然的IO峰值拖慢整体性能

                          所谓IO峰值:突发的大量数据写入,导致瞬间IO压力飙升,导致瞬间IO性能狂跌。

                            dirty_background_ratio = 5
                            dirty_ratio = 80
                            dirty_writeback_centisecs = 500
                            dirty_expire_centisecs = 3000
                            复制


                            此配置通过增大Cache和更加频繁唤醒回刷的方式,解决IO峰值的问题。通过保证脏数据比例保持在一个比较低的水平,当突然出现峰值,也有足够的Cache来缓存数据。




                            Linux内核为每一个块设备分配一个内核线程(flusher threads),线程名为“Writeback",执行体为"wb_workfn",通过workqueue机制实现调度。



                            总结

                            Page Cache是一项重要的性能改进:读缓存在绝大多数情况下是有益无害的;写缓存,内核过段时间再异步刷新到磁盘,对加速磁盘I/O有很好的效果,但是当数据未写入磁盘发生宕机时,可能造成数据丢失。


                            文章转载自大数据从业者,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                            评论