背景

在很多IO场景中,我们经常需要确保数据已经安全的写到磁盘上,以便在系统宕机重启之后还能读到这些数据。但是我们都知道,linux系统的IO路径还是很复杂的,分为很多层,每一层都可能会有buffer来加速IO读写。同时,用户态的应用程序和库函数也可能拥有自己的buffer,这又给IO路径增加了一些复杂性。可见,要想保证数据安全的写到磁盘上,并不是简单调一个write/fwrite就可以搞定的。
那么要怎么做呢?很多人会想到很多办法,比如:fflush()、fsync()、fdatasync()、sync()、open()使用O_DIRECT或O_SYNC标志等。嗯,这些手段(或者某些组合)的确可以保证数据安全的持久化,那么它们之间有什么区别呢?fflush()和fsync()有啥区别?O_DIRECT是啥意思,它可以保证数据安全的持久化吗?O_DIRECT和O_SYNC区别什么?O_SYNC和fsync()呢?fsync能完成msync的功能吗?本文将试图理解、解释这些概念的作用和区别。

Linux IO

所谓一图胜千言,为了解析清楚这些概念的区别,我特意画了一张图,仔细看,应该可以清晰的看出它们的作用和区别。

这里重点说一下O_DIRECT和O_SYNC,首先要明确的是,O_DIRECT只是说数据不会经过page cache(一般用在用户态自己管理buffer)而是直接提交给块设备层,但是不会同步等待数据安全写入磁盘之后才返回(比如数据可能还在块层排队或者在磁盘自己的cache中)。而O_SYNC标志,虽然数据还是会写page cache,但是此时会采用write through的策略,并同步等待数据安全写入磁盘后才会返回。因此如果同时使用O_DIRECT和O_SYNC,则表示数据不会经过page cache并同步等待数据安全写入磁盘才返回,当然这样IO的性能会非常低下。
由于O_DIRECT会bypass page cache,因此如果有另一个进程使用普通的方式读文件,有可能会出现数据不一致的现象,这个也需要注意。
为了做一下辅助说明,此处我贴一下我探讨过程中看过的一些资料。首先是引用open系统调用:
http://man7.org/linux/man-pages/man2/open.2.html
相关参数的说明:

以及innodb相关的文档:
https://lwn.net/Articles/457667/

fsync和fdatasync的区别:
http://man7.org/linux/man-pages/man2/fsync.2.html

msync:
http://man7.org/linux/man-pages/man2/msync.2.html

DAX

其实还有一种IO模式,就是DAX(Direct Access ),是不是看上去和O_DIRECT很像。这种模式需要filesystem和block driver都支持才可以,一般主要用在non volatile memory上,本质上也是绕过page cache直接操作设备。DAX本文先不做深入探讨,后面我会自己写一个支持DAX模式的ramdisk块设备驱动,然后格式化为ext4文件系统并-o dax模式挂载,再来详细研究DAX的IO路径。
最后附上Linux在常见场景下的io路径跟踪:
https://my.oschina.net/fileoptions/blog/3061822

Linux:保证数据安全落盘的更多相关文章

  1. Linux系统:保证数据安全落盘

    在很多IO场景中,我们经常需要确保数据已经安全的写到磁盘上,以便在系统宕机重启之后还能读到这些数据.但是我们都知道,linux系统的IO路径还是很复杂的,分为很多层,每一层都可能会有buffer来加速 ...

  2. Linux/UNIX编程如何保证文件落盘

    本文转载自Linux/UNIX编程如何保证文件落盘 导语 我们编写程序write数据到文件中时,其实数据不会立马写入磁盘,而是会经过层层缓存.每层缓存都有自己的刷新时机,每层缓存都刷新后才会写入磁盘. ...

  3. Java如何保证文件落盘?

    本文转载自Java如何保证文件落盘? 导语 在之前的文章Linux/UNIX编程如何保证文件落盘中,我们聊了从应用到操作系统,我们要如何保证文件落盘,来确保掉电等故障不会导致数据丢失.JDK也封装了对 ...

  4. linux系统数据落盘之细节

      本文节选自这里,原文以mysql innodb系统为例,介绍了数据经过的各层级的buffer和cache,其它系统也有相似的原理,摘录于此. 3.  VFS层 该层的缓冲都放在主机内存中,它的目的 ...

  5. linux入门系列13--磁盘管理之RAID、LVM技术

    前一篇文章学习了磁盘分区.格式化.挂载等相关知识,本文将讲解RAID和LVM技术. 磁盘管理操作主要是运维人员用的较多,如果只是单纯的开发人员,可以先略过本文.但是在很多小公司里往往都是一人多用,运维 ...

  6. 细看INNODB数据落盘

    本文来自:沃趣科技 http://www.woqutech.com/?p=1459 1.  概述 前面很多大侠都分享过MySQL的InnoDB存储引擎将数据刷新的各种情况.我们这篇文章从InnoDB往 ...

  7. 细看InnoDB数据落盘 图解 MYSQL 专家hatemysql

    http://hatemysql.com/?p=503 1.  概述 前面很多大侠都分享过MySQL的InnoDB存储引擎将数据刷新的各种情况.我们这篇文章从InnoDB往下,看看数据从InnoDB的 ...

  8. __细看InnoDB数据落盘 图解 MYSQL

    http://hatemysql.com/?p=503 1.  概述 前面很多大侠都分享过MySQL的InnoDB存储引擎将数据刷新的各种情况.我们这篇文章从InnoDB往下,看看数据从InnoDB的 ...

  9. Linux 桌面玩家指南:20. 把 Linux 系统装入 U 盘打包带走

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

随机推荐

  1. C# 实现NPOI的Excel导出

    技术点: 1.自定义attribute属性 2.通过反射取类及其属性的attribute属性值 3.NPOI包常用属性及方法(我也仅仅知道用到过的,陌生的要么见名知意,要么百度查) 实现功能点: Li ...

  2. Redis作缓存

    缓存策略三要素:缓存命中率   缓存更新策略  最大缓存容量.衡量一个缓存方案的好坏标准是:缓存命中率.缓存命中率越高,缓存方法设计的越好. 三者之间的关系为:当缓存到达最大的缓存容量时,会触发缓存更 ...

  3. @WebServlet注解(Servlet注解)

    @WebServlet 注解的属性 @WebServlet 用于将一个类声明为 Servlet,该注解会在部署时被容器处理,容器根据其具体的属性配置将相应的类部署为 Servlet.该注解具有下表给出 ...

  4. logger命令

    logger是一个shell命令接口,可以通过该接口使用Syslog的系统日志模块,还可以从命令行直接向系统日志文件()写入一行信息. -i 在记录上显示pid进程号 -t 给日志记录打标签 1.直接 ...

  5. 学习JAVAWEB第十七天

    今天还是在做登陆界面,做到后台servlet了 知识点太不熟练了,还得继续做

  6. 计算机电子书 2019 BiliDrive 备份

    下载方式 pip install BiliDriveEx bdex download <link> 链接 文档 链接 传智播客轻松搞定系列 C.C++.Linux.设计模式.7z (33. ...

  7. js-reduce方法源码

    // 数组中的reduce方法源码复写 //先说明一下reduce原理:总的一句,reduce方法主要是把数组遍历, //然后把数组的每个元素传入回调函数中,回调函数怎么处理,就会的到什么样的效果 A ...

  8. Java流程控制01:用户交互Scanner

    Scanner对象 之前我们学习的基本语法并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入.java.Scanner 是java5 的新特征,我们可以通过Sca ...

  9. CF1229D - Wojtek and Card Tricks

    做法一 首先将排列用康托展开映射到整数,并且预处理出排列之间乘法的结果,复杂度 \(\mathcal{O}(k(k!) ^ 2)\). 枚举左端点,有可能分段的右端点至多只有 \(k!\) 个,不妨将 ...

  10. MyEclipse工程中Java Build Path中的JDK版本和Java Compiler Compiler compliance level的区别

    感谢大佬:https://blog.csdn.net/shan9liang/article/details/17266519 问题起源: 今天再在ESB调用WebService测试,需要在jboss上 ...