【转】ext4+delalloc造成单次写延迟增加的分析
转自 http://blog.tao.ma/?p=58
这篇文章是淘宝内核组的刘峥同学在内部技术论坛上发表的一篇文章,但是由于刘峥同学目前没有blog,征得本人同意,贴在我的blog上,如果大家喜欢,请去新浪微博关注他。:)
日前线上在升级到Ext4文件系统后出现应用写操作延迟开销增大的问题。造成这一问题的根源目前已经查明,是由于Ext4文件系统的一个新特性——Delay Allocation造成的。(后面简称delalloc)
在详细分析这一问题之前,先来介绍一下Ext4文件系统的delalloc特性。这一特性简要概括起来就是将以前在buffer IO中每次写操作都会涉及的磁盘块分配过程推迟到数据回写时再进行。我们知道,在进行Buffer Write时,系统的实际操作仅仅是为这些数据在操作系统内分配内存页(page cache)并保存这些数据,等待用户调用fsync等操作强制刷新或者等待系统触发定时回写过程。在数据拷贝到page cache这一过程中,系统会为这些数据在磁盘上分配对应的磁盘块。
而在使用delalloc后,上面的流程会略有不同,在每次Buffer Write时,数据会被保存到page cache中,但是系统并不会为这些数据分配相应的磁盘块,仅仅会查询是否有已经为这些数据分配过磁盘块,以便决定后面是否需要为这些数据分配磁盘块。在用户调用fsync或者系统触发回写过程时,系统会尝试为标记需要分配磁盘块的这些数据分配磁盘块。这样,文件系统可以为这些属于同一个文件的数据分配尽量连续的磁盘空间,从而优化后续文件的访问性能(因为传统机械硬盘顺序读写的性能要比随机读写好很多)。
了解完delalloc特性的工作过程后,我们开始分析线上遇到的问题。线上应用的I/O模式可以简化为一个单线程追加写操作的程序,每秒写入2、3M数据,写操作后等待系统自动将数据回写到磁盘。在使用delalloc后,每次Buffer Write操作,系统都会去查询数据是否分配了磁盘块,这一过程需要获得一把读锁 (i_data_sem)。由于这时还没有触发回写操作,因此可以顺利获取i_data_sem,系统完成数据拷贝工作,并返回。由于仅仅是内存拷贝的过程,所以这一操作速度相当快。当系统开始进行回写操作时,系统会成批为数据分配磁盘块,这一过程同样需要获取i_data_sem,并且需要加写锁以保证数据的一致性。由于使用delalloc后,需要分配的磁盘块比nodelalloc情况下多很多(nodelalloc情况下每5秒文件系统会提交日志触发回写;delalloc情况下,系统会在约每30秒左右触发一次回写),因此这一延迟时间较长。如果这时应用程序进行一次Buffer Write,则该操作在尝试获得i_data_sem时会等待上述磁盘块分配完成。由此造成写操作等待很长时间,从而影响应用程序的响应延迟。
在上面的分析中已经提到,delalloc是将多次磁盘块分配的过程合并到一次中来进行,那么是否真如预想的那样,delalloc的平均延迟会小于nodelalloc的情况呢?我们使用fio来做如下测试:设置bs=4k,单线程每秒追加写入5M,程序运行3分钟,我们来看一下最后fio对延迟的统计结果:
delalloc:
lat (usec): min=2 , max=193466 , avg= 5.86, stdev=227.91
nodelalloc:
lat (usec): min=3 , max=16388 , avg= 7.00, stdev=28.92
从上面的统计结果看,写操作的平均延迟:打开delalloc后为5.86us,关闭delalloc后为7.00us;最小延迟delalloc为2us,nodelalloc为3us;但是最大延迟delalloc为193.466ms,nodelalloc下仅为16.388ms。可见delalloc确实将多个写操作请求集中到了一起来进行。因此在提供较低平均延迟的情况下,会造成某次写操作的延迟较大。
通过上面的分析可以看到,目前会受到Ext4的delalloc特性影响的应用必须具备如下条件:
0. Buffer IO
1. 写操作过程中会涉及磁盘块的分配,主要是记录日志这类追加写操作;
2. 每次写操作后没有刷新数据,而是等待系统自动进行回写;
3. 对延迟有较高要求。
解决方法:关闭delalloc
1. mount -t ext4 -o remount,nodelalloc /${dev} /${mnt};
2. 编辑/etc/fstab中相关mount项,添加nodelalloc挂载参数
【转】ext4+delalloc造成单次写延迟增加的分析的更多相关文章
- ext4文件系统的delalloc选项造成单次写延迟增加的分析
最近我们的服务进程遇到kill -15后处于Z的状态,变为了僵尸进程,经过/proc/{thread_id}/stack查看其上线程的栈,发现是卡在了fwrite的过程中,而我们的系统中所有文件系统挂 ...
- [转载]ext4文件系统的delalloc选项造成单次写延迟增加的分析
转载http://www.cnblogs.com/cobbliu/p/5603472.html 最近我们的服务进程遇到kill -15后处于Z的状态,变为了僵尸进程,经过/proc/{thread_i ...
- C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步
摘要:C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景.该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定, ...
- 使用ReaderWriterLock类实现多用户读/单用户写同步
使用ReaderWriterLock类实现多用户读/单用户写同步[1] 2015-03-12 应用程序在访问资源时是进行读操作,写操作相对较少.为解决这一问题,C#提供了System.Threadin ...
- Python中的单继承与多继承实例分析
Python中的单继承与多继承实例分析 本文实例讲述了Python中的单继承与多继承.分享给大家供大家参考,具体如下: 单继承 一.介绍 Python 同样支持类的继承,如果一种语言不支持继承,类就没 ...
- YII用户注冊和用户登录(二)之登录和注冊在视图通过表单使用YII小物件并分析
2 登录和注冊在视图通过表单使用YII小物件并分析 <?php $form = $this -> beginWidget('CActiveForm', array( 'enableClie ...
- ext4 delalloc相关
ext4文件系统delayed allocation相关研究 最近在一个项目上测试录音时,发现有丢数据的现象.通过串口发现打出了很多overrun的log. overrun是驱动层给上层应用的一个通知 ...
- 熟悉的味道——从Java单例写到C++单例
设计模式中,单例模式是常见的一种.单例模式需要满足以下两个条件: 保证一个类只能创建一个示例: 提供对该实例的全局访问点. 关于单例最经典的问题就是DCL(Double-Checked Lock),今 ...
- EXT4.1表单提交(非AJAX)
Ext.require([ 'Ext.form.*', 'Ext.data.*' ]); Ext.onReady(function(){ Ext.apply(Ext.form.VTypes, { re ...
随机推荐
- jenkins slave启动报错:hudson.util.IOException2: Slave JVM has terminated. Exit code=126
添加mac slave节点报错如下:Expanded the channel window size to 4MB [11/07/14 19:11:54] [SSH] Starting slave p ...
- 0728am thinkphp介绍
- (译)Windows Azure的7月更新:SQL数据库,流量管理,自动缩放,虚拟机
Windows Azure的7月更新:SQL数据库,流量管理,自动缩放,虚拟机 今早我们释出一些很棒的Windows Azure更新.这些新的提升包括:SQL数据库:支持SQL自动导出和一个新的高级层 ...
- ReentrantLock的底层实现机制 AQS
ReentrantLock的底层实现机制是AQS(Abstract Queued Synchronizer 抽象队列同步器).AQS没有锁之类的概念,它有个state变量,是个int类型,为了好理解, ...
- redis安全设置
1. 设置监听ip为本地和内网ip bind 127.0.0.1 192.168.1.99 ## 可以是多个ip,用空格分割 2. 设置监听端口 port 16379 3. 设置密码 在配置文件中加入 ...
- Python日期字符串比较
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 需要用python的脚本来快速检测一个文件内的二个时间日期字符串的大小,其实实现很简单,首先一些 ...
- PentestBox简明使用教程
介绍 PentestBox:渗透测试盒子 顾名思义,这是一个渗透工具包,但是不同于绝大多数国内xx工具包的是,这里集成的大都是Linux下的工具,Kali Linux上面的常用的很多工具这里面也都集成 ...
- SDUT oj 2610
/*题目大意:输入一序列n个数字,然后输入m个询问,每个询问包含左边区间和右边区间,还有a和b,问你这个区间内有几个数大于等于a且小于等于b 做法:树状数组,先求出这个区间内有几个数小于a,然后求这个 ...
- Python学习笔记之函数参数传递 传值还是传引用
在学完Python函数那一章节时,很自然的的就会想到Python中函数传参时传值呢?还是传引用?或者都不是? 在回答上面的问题之前我们先来看看下面的代码: 代码1: def foo(var): v ...
- Mysql主从架构报错-Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work...
在搭建Mysql主从架构过程中,由于从服务器是克隆的主服务器系统,导致主从mysql uuid相同, Slave_IO无法启动,报错如下: The slave I/O thread stops bec ...