Chinaunix首页 | 论坛 | 博客
  • 博客访问: 150946
  • 博文数量: 33
  • 博客积分: 1494
  • 博客等级: 上尉
  • 技术积分: 325
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-24 21:50
文章分类

全部博文(33)

文章存档

2014年(1)

2013年(1)

2012年(2)

2011年(3)

2010年(26)

我的朋友

分类: LINUX

2012-10-17 19:16:54

当你在程序中试图将数据写入文件的时候,Linux系统并不会马上将数据写入disk之中,而是先将它们临时存放在memory的一块区域,那块区域叫做page cache(页高速缓冲存储器)。我们可以通过cat命令从/proc/meminfo文件中查看系统memory的详细信息,信息格式如下:

MemTotal:      3950112 kB

MemFree:        622560 kB

Buffers:         78048 kB

Cached:        2901484 kB

SwapCached:          0 kB

Active:        3108012 kB

Inactive:        55296 kB

HighTotal:           0 kB

HighFree:            0 kB

LowTotal:      3950112 kB

LowFree:        622560 kB

SwapTotal:     4198272 kB

SwapFree:      4198244 kB

Dirty:             416 kB

Writeback:           0 kB

Mapped:         999852 kB

Slab:            57104 kB

Committed_AS:  3340368 kB

PageTables:       6672 kB

VmallocTotal: 536870911 kB

VmallocUsed:     35300 kB

VmallocChunk: 536835611 kB

HugePages_Total:     0

HugePages_Free:      0

Hugepagesize:     2048 kB

上面每一项的具体含义从linux官方网站上都能找到相关文档解释,我们今天只关注两个指标,一个是Cached,另一个是Dirty。如上所示Cached:2901484 KB,指的是page cache的大小为2901484 KB,Dirty:  416KB指的是有416KB的数据存于page cache中,等待写入disk。我们上面讲到了,当有数据写入文件时,数据会先缓存在page cache中,我们可以认为内存中的这部分数据是系统Dirty数据,很显然随着数据的不断写入,Dirty会越来越大,那会不会出现page cache空间被耗尽进而使得系统memory吃紧呢?不用想,答案肯定是No,我下面要讲的就是这篇文章的关键了------linux将数据flush到disk的具体机制。

         在linux系统中,有一个专门负责将page cache中的数据flush到disk的进程,叫pdflush。在系统运行任意时刻,都有2到8个pdflush的守候服务线程在running。同样你可以通过cat命令去查看/proc/sys/vm/nr_pdflush_threads这个文件,里面记录着此刻的pdflush线程数。既然pdflush线程一直存在,它如何决定哪些数据要flush到disk,哪些需要继续留在page cache中呢?一般来说,按照系统默认的内核配置,在以下两种情况下,page cache中的数据会开始被pdflush线程认为可以flush到disk中。第一,数据在page cache中的时间超过30秒;第二,系统Dirty值超过可用memory的10%。如果你的程序在连续几个小时不断的写数据到文件中,数据量还比较大的话,你可以看到系统Dirty(待写入disk的数据)值一直保持在可用memory的10%左右(这一点我已经验证过),就是因为有了pdflush线程的服务,使得数据能够及时flush到disk中,从而避免了memory吃紧进而系统挂掉的事情发生。有了这两项约束机制,一般情况下disk的写服务都能得到很好的管理,但pdflush既然作为一个程序存在,就必然有一个负载力的问题。我们可以举这么一个例子,假设淘宝公司希望在每一笔交易发生的时候都以日志的形式把下面几项信息写入文件记录下来(淘宝具体怎么做的我不知道,但我觉得淘宝肯定有这样的行为):用户名、用户性别、用户地址、所购买物品名称、所购买物品类别、交易金额、交易时间。我就先列举这几项信息,也许你会觉得把这几项信息打印出来有神马用,殊不知在当下时代最宝贵的东东莫过于海量信息了,尤其是用户的消费行为信息。从我们学计算机人的眼里来看,拥有海量信息是进行数据挖掘和机器学习的前提,淘宝可以从中分析出不同年龄段人的消费习惯、大部分人所喜欢购物的时机等等,从小了说通过分析出来的这些信息淘宝可以有针对性的去改善服务,从大了说,决策者可以根据分析出来的这些信息去调整公司发展的战略。好了,我相信我说的足够啰嗦了,我们言归正传,淘宝每年的交易额上万亿,交易极其频繁,如果再赶上个好日子光棍节促销一把,瞬间交易量非常大,如果所有交易信息都打印到disk的话,估计pdflush进程根本承受不住,无法将page cache中的数据及时的flush到disk中,也就不能保证系统Dirty值维持在可用memory的10%以下了,这种情况持续时间长了系统必然会挂掉,肿么办呢?这就是我们一般打死都不会care的一种场景,当系统Dirty值达到可用memory的40%时,系统会停掉一切写服务,然后集中精力通过pdflush线程将page cache中的数据全部flush到disk。这种情况是必须要避免的,比如淘宝后台如果出现这种情况,系统一本心思去flush数据到disk了,在此期间,所有的订单提交估计都要失败,这对于一个知名的电子商务公司必然是不能接受的,无论从盈利角度还是服务信誉角度。那怎么办呢?有两种方法可以帮助改善和解决这个问题,一是修改内核参数,二是人为强制将page cache中的数据flush到disk,不让系统Dirty达到40%的阈值。跟flush disk相关的内核参数有很多,我今天主要讲两个:/proc/sys/vm/dirty_background_ratio 和/proc/sys/vm/dirty_writeback_centisecs。第一个内核参数控制文件系统的pdflush进程,单位是百分比(默认为10),当写缓冲使用到系统内存达到此比例时,pdflush开始向磁盘写数据刷新磁盘。第二个参数控制内核的脏数据刷新进程pdflush的运行间隔,单位是 1/100 秒(默认500)。当系统有持续大量的数据写磁盘时,修改这两个参数(将二者都适量调小)可以很好的提高性能,降低系统dirty。当然修改内核参数的方式不能用vi打开文件,修改方式如下:

echo "2" >/proc/sys/vm/dirty_background_ratio

echo "100">/proc/sys/vm/dirty_writeback_centisecs

当然,修改参数只是对系统运作的一种调优,要彻底解决这个问题还是需要人为进行强制干预,那就是使用fsync系统调用,fsync函数可以强制将你每次写入的数据flush到磁盘中(类似于一个受你控制的pdflush进程),这样一来就再也不用担心系统Dirty太大的问题出现了。当然系统的写磁盘机制肯定是最优的,人为干预写数据自然会带来系统开销,影响服务性能,所以真正使用时还需要仔细权衡利弊,不可贸然使用。

阅读(1299) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~