前言

最近遇到了一起跟磁盘相关的线上故障,借此总结一下之前不太了解的Linux磁盘缓存相关的知识。

总的来说磁盘缓存出现的原因大概有两个:第一是访问磁盘的速度远慢于访问内存的速度,通过在内存中缓存磁盘内容可以提高访问速度;第二是根据程序的局部性原理,数据一旦被访问过,就很有可能在短时间内再次被访问,所以在内存中缓存磁盘内容可以提高程序运行速度。

局部性原理

程序局部性原理:程序在执行时呈现出局部性规律,即在一段时间内,整个程序的执行仅限于程序中的某一部分。相应地,执行所访问的存储空间也局限于某个内存区域,具体来说,局部性通常有两种形式:时间局部性和空间局部性。

时间局部性:被引用过一次的存储器位置在未来会被多次引用。

空间局部性:如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。

页缓存

Linux系统中为了减少对磁盘的IO操作,会将打开的磁盘内容进行缓存,而缓存的地方则是物理内存,进而将对磁盘的访问转换成对内存的访问,有效提高程序的速度。Linux的缓存方式是利用物理内存缓存磁盘上的内容,称为页缓存(page cache)。

页缓存是由内存中的物理页面组成的,其内容对应磁盘上的物理块。页缓存的大小会根据系统的内存空闲大小进行动态调整,它可以通过占用内存以扩张大小,也可以自我收缩以缓解内存使用压力。

在虚拟内存机制出现以前,操作系统使用块缓存系列,但是在虚拟内存出现以后,操作系统管理IO的粒度更大,因此采用了页缓存机制,页缓存是基于页的、面向文件的缓存机制。

页缓存的读取

Linux系统在读取文件时,会优先从页缓存中读取文件内容,如果页缓存不存在,系统会先从磁盘中读取文件内容更新到页缓存中,然后再从页缓存中读取文件内容并返回。大致过程如下:

  1. 进程调用库函数read发起读取文件请求
  2. 内核检查已打开的文件列表,调用文件系统提供的read接口
  3. 找到文件对应的inode,然后计算出要读取的具体的页
  4. 通过inode查找对应的页缓存,1)如果页缓存节点命中,则直接返回文件内容;2)如果没有对应的页缓存,则会产生一个缺页异常(page fault)。这时系统会创建新的空的页缓存并从磁盘中读取文件内容,更新页缓存,然后重复第4步
  5. 读取文件返回

所以说,所有的文件内容的读取,无论最初有没有命中页缓存,最终都是直接来源于页缓存。

页缓存的写入

因为页缓存的存在,当一个进程调用write时,对文件的更新仅仅是被写到了文件的页缓存中,让后将对应的页标记为dirty,整个过程就结束了。Linux内核会在周期性地将脏页写回到磁盘,然后清理掉dirty标识。

由于写操作只会把变更写入页缓存,因此进程并不会因此为阻塞直到磁盘IO发生,如果此时计算机崩溃,写操作的变更可能并没有发生在磁盘上。所以对于一些要求比较严格的写操作,比如数据系统,就需要主动调用fsync等操作及时将变更同步到磁盘上。读操作则不同,read通常会阻塞直到进程读取到数据,而为了减少读操作的这种延迟,Linux系统还是用了“预读”的技术,即从磁盘中读取数据时,内核将会多读取一些页到页缓存中。

回写线程

页缓存的回写是由内核中的单独的线程来完成的,回写线程会在以下3种情况下进行回写:

  1. 空闲内存低于阈值时。当空闲内存不足时,需要释放掉一部分缓存,由于只有不脏的页才能被释放,所以需要把脏页都回写到磁盘,使其变为可回收的干净的页。
  2. 脏页在内存中处理时间超过阈值时。这是为了确保脏页不会无限期的留在内存中,减少数据丢失的风险。
  3. 当用户进程调用sync和fsync系统调用时。这是为了给用户进程提供强制回写的方法,满足回写要求严格的使用场景。

回写线程的实现

名称 版本 说明
bdflush 2.6版本以前 bdflush 内核线程在后台运行,系统中只有一个 bdflush 线程,当内存消耗到特定阀值以下时,bdflush 线程被唤醒。kupdated 周期性的运行,写回脏页。 但是整个系统仅仅只有一个 bdflush 线程,当系统回写任务较重时,bdflush 线程可能会阻塞在某个磁盘的I/O上,导致其他磁盘的I/O回写操作不能及时执行。
pdflush 2.6版本引入 pdflush 线程数目是动态的,取决于系统的I/O负载。它是面向系统中所有磁盘的全局任务的。 但是由于 pdflush 是面向所有磁盘的,所以有可能出现多个 pdflush 线程全部阻塞在某个拥塞的磁盘上,同样导致其他磁盘的I/O回写不能及时执行。
flusher线程 2.6.32版本以后引入 flusher 线程的数目不是唯一的,同时flusher线程不是面向所有磁盘的,而是每个flusher线程对应一个磁盘

页缓存的回收

Linux中页缓存的替换逻辑是一个修改过的LRU实现,也称为双链策略。和以前不同,Linux维护的不再是一个LRU链表,而是维护两个链表:活跃链表和非活跃链表。处于活跃链表上的页面被认为是“热”的且不会被换出,而在非活跃链表上的页面则是可以被换出的。在活跃链表中的页面必须在其被访问时就处于非活跃链表中。两个链表都被伪LRU规则维护:页面从尾部加入,从头部移除,如同队列。两个链表需要维持平衡–如果活跃链表变得过多而超过了非活跃链表,那么活跃链表的头页面将被重新移回到非活跃链表中,一遍能再被回收。双链表策略解决了传统LRU算法中对仅一次访问的窘境。而且也更加简单的实现了伪LRU语义。这种双链表方式也称作LRU/2。更普遍的是n个链表,故称LRU/n。

总结

在这次遇到的线上故障中,根本原因在于在业务逻辑中使用了临时文件做缓存,一个临时文件创建后如果在短时间内删除,这时候对这个文件的操作都是在页缓存内进行,不会实际回写到磁盘。当程序出现问题响应变慢时,临时文件存活时间变长,就可能会使其被回写到磁盘上,导致磁盘压力过大,进而影响整个系统。

- - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛

原文地址:一文了解Linux磁盘缓存机制 - Linux内核 - 内核技术中文网 - 构建全国最权威的内核技术交流分享论坛(版权归原作者所有,侵删)

一文了解Linux磁盘缓存机制相关推荐

  1. linux缓存详解,Linux磁盘缓存机制详解

    磁盘缓存出现的原因大概有两个:一是访问磁盘的速度远慢于访问内存的速度,通过在内存中缓存磁盘内容可以提高访问速度:二是根据程序的局部性原理,数据一旦被访问过,就很有可能在短时间内再次被访问,所以在内存中 ...

  2. linux 命令缓存机制(命令:hash) | hash -r使用场景和作用

    文章目录 linux 命令缓存机制(命令:hash) | hash -r使用场景和作用 什么是hash 缓存表 hash命令 hash -r使用场景和作用 linux 命令缓存机制(命令:hash) ...

  3. linux 磁盘缓存设置,Linux下的磁盘缓存

    前段时间在开发一个使用SSD做缓存的系统,在高速写入数据时会出现大量的磁盘缓存.太多的磁盘缓存如果没有及时的写入磁盘中,在机器出现问题时是非常危险的,这样会导致很多的数据丢失,但是如果实时的将数据刷入 ...

  4. linux 编译缓存,Linux磁盘缓存(disk cache)详解

    在Linux系统里通过free命令,我们经常可以看到类似下面的输出: $ free -m total used free shared buffers cached Mem: 24097 21665 ...

  5. 一文搞懂浏览器缓存机制

    最近在项目中遇到了 IE浏览器因缓存问题未能成功向后端发送 GET类型请求 的bug,然后顺藤摸瓜顺便看了看缓存的知识,觉得有必要总结跟大家分享一下. 在前端开发中,性能一直都是被大家所重视的一点,然 ...

  6. Android/Linux 磁盘写入缓存/等待时间 参数修改

    Linux系统当进行文件写操作时,并不会将数据立马写入磁盘,而是写写到缓存,等待达到占用内存一定比例或超过一定时间才会批量将这些缓存数据写入磁盘,这样可以减少IO操作,提升性能和磁盘寿命.如果数据还没 ...

  7. linux开启swap(磁盘缓存)操作

    转载 2014年04月26日 14:41:15 4470 由于工作需要,要帮助同事查看linux服务器的缓存开启情况,经过查找资料,可确定通过以下方法确定Linux磁盘缓存是否已开启. 1.命令行下执 ...

  8. 磁盘与内存的亲密关系 -磁盘缓存和虚拟内存

    内存和磁盘的亲密关系 1.前提 内存与磁盘都是存储部件,内存利用电流来存储.磁盘利用磁效应来存储.内存高速高价,磁盘低速廉价. 存储在磁盘中的程序必须先加载到内存中才能运行.这是因为cpu需要程序计数 ...

  9. linux下的缓存机制及清理buffer/cache/swap的方法梳理

    1)缓存机制介绍 在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果 ...

最新文章

  1. mybatis中statementHandler的设计与实现
  2. JMM内存模型如何为并发保驾护航
  3. 恩施茶旅谋定乡村-农业大健康·万祥军:侗乡第一寨促生态
  4. Android Studio安装genymotion模拟器
  5. JAVA基础学习预科部分 (Markdown + dox)2021/2/22持续更新中
  6. Linux网络编程--sendfile零拷贝高效率发送文件
  7. sql server 死锁排查
  8. php yii2模块,Yii2 中关于模块(Modules)的使用及配置
  9. Oracle EBS R12 电子技术参考手册 - eTRM (电子文档)
  10. 今日头条推荐算法原理
  11. 互联网舆情系统的架构实践
  12. Boxy SVG for Mac版矢量图编辑软件
  13. 洲际酒店集团发布全新奢华精选品牌;凯悦27亿美元收购奢华酒店运营集团ALG | 美通社头条...
  14. 新概念英语1册57课
  15. 五大浏览器:chrome---Blink IE--Trident firebox--Gecko safari--Webkit opera--Blink
  16. C 程序设计语言(第2版)
  17. Android手机安装apk 提示应用未安装
  18. git commit -m 提交忽略代码校验
  19. MAVLink协议详解
  20. 对3Q大战的一点见解

热门文章

  1. Excel中在每一行前均插入几个空行的步骤
  2. 在win10系统上配置phpstorm 2018+php7.3+xdebug的开发环境
  3. linux图形界面基本概念
  4. c# 避开淘宝助理检测上传宝贝描述含其他店铺图片的小工具【原】
  5. 科普:什么是移动订货系统?移动订货系统有哪些功能?
  6. Bonaparte:贝叶斯网在灾难遇难者识别(DVI)中的应用
  7. java gridfs_GridFS实现原理
  8. Hibernate与代理模式
  9. 【蓝桥杯算法题】用java遍写税收计算
  10. Word里全角转换成半角