本文节选自这里,原文以mysql innodb系统为例,介绍了数据经过的各层级的buffer和cache,其它系统也有相似的原理,摘录于此。

3.  VFS层

该层的缓冲都放在主机内存中,它的目的主要是在操作系统层缓冲数据,避免慢速块设备读写操作影响了IO的响应时间。

3.1.  细究O_DIRECT/O_SYNC标签

在前面redo log buffer和innodb buffer pool的讨论中涉及到很多数据刷新和数据安全的问题,我们在本节中,专门讨论O_DIRECT/O_SYNC标签的含义。

我们打开一个文件并写入数据,VFS和文件系统是怎么把数据写到硬件层列,下图展示了关键的数据结构:

图 4  VFS cache图

该图引用自The linux kernel’s VFS Layer。

图中,我们看到该层中主要有page_cache/buffer cache/Inode-cache/Directory cache。其中page_cache/buffer cache主要用于缓冲内存结构数据和块设备数据。而inode-cache用于缓冲inode,directory-cache用于缓冲目录结构数据。

根据文件系统和操作系统的不同,一般来说对一个文件的写入操作包括两部分,对数据本身的写入操作,以及对文件属性(metadata元数据)的写入操作(这里的文件属性包括目录,inode等)。

了解了这些以后,我们就能够比较简单的说清楚各个标志的意义了:

 

page cache

buffer cache

inode cache

dictory cache

O_DIRECT

write bypass

write bypass

write & no flush

write & no flush

O_DSYNC/fdatasync()

write & flush

write & flush

write & no flush

write & no flush

O_SYNC/fsync()

write & flush

write & flush

write & flush

write & flush

                                    表格 3 VFS cache刷新表

l   O_DSYNC和fdatasync()的区别在于:是在每一个IO提交的时刻都针对对应的page cache和buffer cache进行刷新(即O_DSYNC,在write操作成功返回前已完成刷新);还是在一定数据的写操作以后调用fdatasync()的时刻对整个page cache和buffer cache进行刷新。O_SYNC和fsync()的区别同理。

l   page cache和buffer cache的主要区别在于一个是面向实际文件数据,一个是面向块设备。在VFS上层使用open()方式打开那些使用mkfs做成文件系统的文件,你就会用到page cache和buffer cache,而如果你在Linux操作系统上使用dd这种方式来操作Linux的块设备,你就只会用到buffer cache。

l   O_DSYNC和O_SYNC的区别在于:O_DSYNC告诉内核,当向文件写入数据的时候,只有当数据写到了磁盘时,写入操作才算完成(write才返回成功)。O_SYNC比O_DSYNC更严格,不仅要求数据已经写到了磁盘,而且对应的数据文件的属性(例如文件inode,相关的目录变化等)也需要更新完成才算write操作成功。可见O_SYNC较之O_DSYNC要多做一些操作。

l   Open()的referense中还有一个O_ASYNC,它主要用于terminals, pseudoterminals, sockets, 和pipes/FIFOs,是信号驱动的IO,当设备可读写时发送一个信号(SIGIO),应用进程捕获这个信号来进行IO操作。

l   O_SYNC和O_DIRECT都是同步写,也就是说只有写成功了才会返回。

回过头来,我们再来看innodb_flush_log_at_trx_commit的配置就比较好理解了。O_DIRECT直接IO绕过了page cache/buffer cache以后为什么还需要fsync()了,就是为了把directory cache和inode cache元数据也刷新到存储设备上。

而由于内核和文件系统的更新,有些文件系统能够保证保证在O_DIRECT方式下不用fsync()同步元数据也不会导致数据安全性问题,所以InnoDB又提供了O_DIRECT_NO_FSYNC的方式。

当然,O_DIRECT对读和对写都是有效的,特别是对读,它可以保证读到的数据是从存储设备中读到的,而不是缓存中的。避免缓存中的数据和存储设备上的数据是不一致的情况(比如你通过DRBD将底层块设备的数据更新了,对于非分布式文件系统,缓存中的内容和存储设备上的数据就不一致了)。但是我们这里主要讨论缓冲(写buffer),就不深入讨论了。这个问题了。

3.2.  O_DIRECT优劣势

在大部分的innodb_flush_method参数值的推荐中都会建议使用O_DIRECT,甚至在percona server分支中还提供了ALL_O_DIRECT,对日志文件也使用了O_DIRECT方式打开。

3.2.1.  优势:

l   节省操作系统内存:O_DIRECT直接绕过page cache/buffer cache,这样避免InnoDB在读写数据少占用操作系统的内存,把更多的内存留个innodb buffer pool来使用。

l   节省CPU。另外,内存到存储设备的传输方式主要有poll,中断和DMA方式。使用O_DIRECT方式提示操作系统尽量使用DMA方式来进行存储设备操作,节省CPU。

3.2.2.  劣势

l   字节对齐。O_DIRECT方式要求写数据时,内存是字节对齐的(对齐的方式根据内核和文件系统的不同而不同)。这就要求数据在写的时候需要有额外的对齐操作。可以通过/sys/block/sda/queue/logical_block_size知道对齐的大小,一般都是512个字节。

l   无法进行IO合并。O_DIRECT绕过page cache/buffer cache直接写存储设备,这样如果对同一块数据进行重复写就无法在内存中命中,page cache/buffer cache合并写的功能就无法生效了。

l   降低顺序读写效率。如果使用O_DIRECT打开文件,则读/写操作都会跳过cache,直接在存储设备上读/写。因为没有了cache,所以文件的顺序读写使用O_DIRECT这种小IO请求的方式效率是比较低的。

总的来说,使用O_DIRECT来设置innodb_flush_method并不是100%对所有应用和场景都是适用的。

4.  存储控制器层

该层的缓冲都放在存储控制器的对应板载cache中,它的目的主要是在存储控制器层缓冲数据,避免慢速块设备读写操作影响了IO的响应时间。

当数据被fsync()等刷到存储层时,首先会发送到存储控制器层。常见的存储控制器就是Raid卡,而目前大部分的Raid卡都有1G或者更大的存储容量。这个缓冲一般为易失性的存储,通过板载电池/电容来保证该“易失性的存储”的数据在机器断电以后仍然会同步到底层的磁盘存储介质上。

关于存储控制器我们有一些几个方面需要注意的:

  1. write back/write through:

针对是否使用缓冲,一般的存储控制器都提供write back和write through两种方式。write back方式下,操作系统提交的写数据请求直接写入到缓冲中就返回成功;write through方式下,操作系统提交的写数据请求必须要真正写到底层磁盘介质上才返回成功。

  1. 电池/电容区别:

为了保证机器掉电以后在“易失性”缓冲中的数据能够及时刷新到底层磁盘介质上,存储控制器上都有电池/电容来保证。普通的电池有容量衰减的问题,也就是说每隔一段时间,板载的电池都要被控制充放电一次,以保证电池的容量。在电池充放过程中,被设置为write-back的存储控制器会自动变为write through。这个充放电的周期(Learn Cycle周期)一般为90天,LSI卡可以通过MegaCli来查看:

#MegaCli -AdpBbuCmd -GetBbuProperties-aAll

BBU Properties for Adapter: 0

Auto Learn Period: 90 Days

Next Learn time: Tue Oct 14 05:38:43 2014

Learn Delay Interval:0 Hours

Auto-Learn Mode: Enabled

如果你每隔一段时间发现IO请求响应时间突然慢下来了,就有可能是这个问题哦。通过MegaCli -AdpEventLog -GetEvents -f mr_AdpEventLog.txt -aALL的日志中的Event Description: Battery started charging就可以确定是否发生了发生了充放电的情况。

由于电池有这个问题,新的Raid卡会配置电容来保证“易失性”缓冲中的数据能够及时刷新到底层磁盘介质上,这样就没有充放电的问题了。

  1. read/write ratio:

HP的smart array提供对cache的读和写的区别(Accelerator Ratio),

hpacucli ctrl all show config detail|grep 'Accelerator Ratio'

Accelerator Ratio: 25% Read / 75% Write

这样你就可以根据应用的实际情况来设置用于缓存读和缓冲写的cache的比例了。

  1. 开启Direct IO

为了能够让上层的设备使用Direct IO方式来绕过raid卡,对Raid需要设置开启DirectIO方式:

/opt/MegaRAID/MegaCli/MegaCli64 -LDSetProp -Direct -Immediate -Lall -aAll

  1. LSI flash raid:

上面我们提到了“易失性”缓冲,如果我们现在有一个非易失性的缓冲,并且容量达到几百G,这样的存储控制器缓冲是不是更能给底层设备提速?作为老牌的Raid卡厂商,LSI目前就有这样的存储控制器,使用write back方式和比较依赖存储控制器缓冲的应用可以考虑使用这种类型的存储控制器。

  1. write barriers

目前raid卡的cache是否有电池或者电容保护对Linux来说是不可见的,所以Linux为了保证日志文件系统的一致性,默认会打开write barriers,也就是说,它会不断的刷新“易失性”缓冲,这样会大大降低IO性能。所以如果你确信底层的电池能够保证“易失性”缓冲会刷到底层磁盘设备的话,你可以在磁盘mount的时候加上-o nobarrier。

5.  磁盘控制器层

该层的缓冲都放在磁盘控制器的对应板载cache中。存储设备固件(firmware)会按规则排序将写操作真正同步到介质中去。这里主要是保证写的顺序性,对机械磁盘来说,这样可以尽量让一次磁头的移动能够完成更多的磁碟写入操作。

一般来说,DMA控制器也是放在磁盘这一层的,通过DMA控制器直接进行内存访问,能够节省CPU的资源。

对于机械硬盘,因为一般的磁盘设备上并没有电池电容等,无法保证在机器掉电时磁盘cache里面的所有数据能够及时同步到介质上,所以我们强烈建议把disk cache关闭掉。

Disk cache可以在存储控制器层关闭。例如,使用MegaCli关闭的命令如下:

MegaCli -LDSetProp -DisDskCache   -Lall -aALL

转载于:https://www.cnblogs.com/wuhuiyuan/p/4648725.html

linux系统数据落盘之细节相关推荐

  1. redis相关(搭建和数据落盘)

    一. redis的编译安装 1.依赖的系统包 yum install -y wget gcc make tcl 2.下载包地址 1.各个版本redis的下载地址 http://download.red ...

  2. kafka数据 落盘_终于知道Kafka为什么这么快了!

    " 无论 Kafka 作为 MQ 也好,还是作为存储层也罢,无非就是两个功能,一是 Producer 生产的数据存到 Broker,二是 Consumer 从 Broker 读取数据. 图片 ...

  3. 云小课|三大灵魂拷问GaussDB(DWS)数据落盘安全问题

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:GaussDB(D ...

  4. 对比五种制作Linux系统的U盘启动盘的工具

    在网上存在很多制作Linux系统的U盘启动软件,也有很多教程,比如说是UNetBootin.wubi.UltraISO.syslinux.LinuxLive USB Creator一些比较主流的软件, ...

  5. linux导出文件夹到u盘,Linux系统放到U盘上直接在U盘上运行Linux

    以下使用dos+grub4dos启动Ubuntulinux进入u盘目录,这种开启方法便于加入PE和dos工具箱制作多重启动盘. 优盘之家 1.引导dos启动 U盘之家 启动UltraISO,选择菜单& ...

  6. linux导出文件夹到u盘,把Linux系统放在U盘上直接在U盘上运行Linux

    Linux以它的高效和灵活的特性深受着某些用户的喜爱,但是又不方便平时操作的习惯,如果用户不想在电脑上安装Linux系统,又想使用Linux系统的话,这里教大家一个好方法,把Linux系统放在U盘上, ...

  7. linux怎么u盘挂载到根目录,Linux系统挂载U盘方法

    Linux系统挂载U盘方法 1. 挂载前首先要确认U盘的格式是Linux可识别的文件系统 Window常用的FA T32文件系统:vfat Window常用的NTFS文件系统:ntfs OS/2用的文 ...

  8. linux进入u盘目录,Linux系统放在U盘上直接在U盘上运行Linux

    Linux系统放在U盘上直接在U盘上运行Linux 今天给大家分享这个教程,大家有需要的可以试试看 以下使用dos+grub4dos启动Ubuntu,这种启动方式方便加入PE和dos工具箱制作多重启动 ...

  9. u盘linux 路由器,如何构建Linux系统下U盘路由器防火墙

    如何构建Linux系统下U盘路由器防火墙 步骤十二:高级应用,以其他存储介质使用coyote Linux coyote Linux 官方网址的链接说明其不支持USB启动(http://www.vort ...

最新文章

  1. 【组队学习】【26期】编程实践(Django网站开发)
  2. ggplot2笔记6:标度、轴和图例
  3. 微信小程序-01-项目组成文件介绍(入门篇)
  4. 利用django中间件CsrfViewMiddleware防止csrf攻击
  5. 优化 最长上升子序列_LIS - 最长上升子序列 (二分优化)
  6. 华三 h3c ACL配置
  7. ERP实施项目的计划阶段要点分析
  8. 【LaTeX入门】15 在文章中添加脚注
  9. 华为服务器忘记系统密码忘了,服务器忘记密码重置
  10. 山东省第八届 ACM 省赛 Parity check (规律、水)
  11. 26丨案例:手把手带你理解TPS趋势分析*
  12. Oracle-SQLLDR加载TPC-DS数据
  13. 域渗透|NTLM 中继攻击
  14. Python黑帽子-黑客与渗透测试编程之道
  15. 如何从javascript直接调用word插件
  16. 房友系统连接不上服务器,房友系统服务器地址
  17. 网络基本功:三次握手及四次挥手
  18. mysql scn_Oracle scn之基本概念
  19. 企业申请车辆蓄电池E-mark认证要提前准备些什么资料?
  20. 中兴新支点Linux桌面操作系统初次使用体验

热门文章

  1. JVM内存结构|虚拟机栈
  2. mysql恢复语句报错_php对于mysql恢复数据的时候,只能恢复一条!然后就会报错!但把sql语句直接贴到数据库里面是可以执行的!...
  3. sklearn 决策树例子_机器学习|决策树的生成过程是怎样?(一)
  4. java 字符串模糊匹配_Java实现伪查询(全匹配+模糊匹配)
  5. python discover()没有加载测试用例_对python_discover方法遍历所有执行的用例详解
  6. mysql query sql_sql:query 标签
  7. python退出mainloop_python - Python Turtle mainloop()的用法 - 堆栈内存溢出
  8. 我一个女孩子居然做了十年硬件。​。。
  9. 漫画科普:芯片是如何设计出来的
  10. ST-Link如何秒变J-link,手把手教你实现该功能