Linux-IO篇
硬件-驱动-文件系统-挂载-应用程序
硬盘:
机械
目前为止,空间大,价格低廉
缺点,有机械寻道时间。
SATA 7200转/分
SCSI 10000/15000转/分
闪存
价格贵、空间小、写入有次数限制
速度快,读取没有机械的寻道时间。
结合机械一起使用,写的时候用机械,读用SSD。
内存
快
容量、断电之后数据丢失、成本太高
RAID从中不可缺少。
磁盘速度:
hdparm -T -t /dev/sda
=======================
I/O队列调度算法:
/sys/block/hda/queue/scheduler
deadline 最终期限的控制
anticipatory 预测机制
noop 没有策略
[cfq] 完全公平
文档
[root@mercury Documentation]# ls kernel-parameters.txt
kernel-parameters.txt
[root@mercury Documentation]# ls block/
as-iosched.txt ioprio.txt
barrier.txt request.txt
biodoc.txt stat.txt
deadline-iosched.txt switching-sched.txt
硬盘 <--- 驱动 <---IO-scheduler <--- FileSystem ...
<- Read I/O <----- cat less ....
<- Write I/O <----- dd vim(wq)...
=====队列=====
针对比较“急”应用。
ERP RSS 。。。
vim /etc/fstab
先读 后写
所以读过期时间 要小于写的过期时间。
过期时间一到必须立即离开队列进入磁盘。
问题:
<---1磁道1扇区 磁头移到到1道
<---2磁道1扇区 磁头移动到2道
<---1磁道2扇区 磁头移到到1道
<---2磁道2扇区 磁头移动到2道
如果能在1磁道连续读取1 、2 扇区,那么将节约磁头臂移动时间。
预测机制:
echo "anticipatory" > /sys/block/hda/queue/scheduler
ls /sys/block/hda/queue/iosched/
antic_expire read_expire
est_time write_batch_expire
read_batch_expire write_expire
cat /sys/block/hda/queue/iosched/read_expire
125
cat /sys/block/hda/queue/iosched/write_expire
250
cat /sys/block/hda/queue/iosched/antic_expire
6
硬盘 <--- 驱动 <---IO-scheduler <--- FileSystem ...
<- Read I/O <----- cat less ....
<- Write I/O <----- dd vim(wq)...
=====队列=====
请求进入队列后,至少停6毫秒
如果队列中有:
<---1磁道1扇区 磁头移到到1道
<---2磁道1扇区 磁头移动到2道
<---1磁道2扇区 磁头移到到1道
<---2磁道2扇区 磁头移动到2道
发现有相邻的请求,那么排序。
<---1磁道1扇区 磁头移到到1道
<---1磁道2扇区
<---2磁道1扇区 磁头移动到2道
<---2磁道2扇区
应用:
WEB、FTP
问题:
进程很多的时候
A 进程 1 2 3
B 进程 4 5 6
C 进程 9
多进程时,会有失公平。
完全公平:
echo "cfq" > /sys/block/hda/queue/scheduler
ls /sys/block/hda/queue/iosched/
back_seek_max queued
back_seek_penalty slice_async
fifo_expire_async slice_async_rq
fifo_expire_sync slice_idle
quantum slice_sync
最后队列长度:
cat /sys/block/hda/queue/iosched/queued
8
每次在逻辑队列中取4个:
cat /sys/block/hda/queue/iosched/quantum
4
硬盘 <--- 驱动 <---IO-scheduler <--- FileSystem ...
<- Read I/O <----- cat less ....
<- Write I/O <----- dd vim(wq)...
=====队列=====
===逻辑队列(64)
==== ===
最后队列 ===
==== ===
===
.....
===
应用:
DB
noop 没有策略
考虑磁盘介质改变,SSD,MemDISK
==================
EXT4
XFS
JFS
ReiserFS
Btrfs(-)
==================
XFS\JFS\REISERFS
INSTALL RPM:
rpm -ivh kernel-2.6.18-194.el5.src.rpm
确定系统中有安装 rpm-build-4.4.2.3-18.el5
BUILD SOURCE:
rpmbuild -bp --target=$(uname -m) /usr/src/redhat/SPECS/kernel-2.6.spec
DIR:
/usr/src/redhat/BUILD/kernel-2.6.18/linux-2.6.18.i686
CONFIG:
cp /boot/config-2.6.18-194.el5 .config
vim Makefile
EXTRAVERSION = -194.el5
make oldconfig
mkdir .tmp_versions
make menuconfig
选择三个文件系统,之后保存退出:
File systems --->
<M> Reiserfs support
<M> JFS filesystem support
<M> XFS filesystem support
make fs/xfs/xfs.ko
make fs/jfs/jfs.ko
make fs/reiserfs/reiserfs.ko
mkdir /lib/modules/`uname -r`/kernel/fs/reiserfs
mkdir /lib/modules/`uname -r`/kernel/fs/xfs
mkdir /lib/modules/`uname -r`/kernel/fs/jfs
cp ./fs/reiserfs/reiserfs.ko /lib/modules/`uname -r`/kernel/fs/reiserfs
cp ./fs/xfs/xfs.ko /lib/modules/`uname -r`/kernel/fs/xfs
cp ./fs/jfs/jfs.ko /lib/modules/`uname -r`/kernel/fs/jfs
depmod -a
>---------->----------->
格式化工具:
EXT4
rpm -ivh e4fsprogs-1.41.9-3.el5.i386.rpm
JFS:
tar xf jfsutils-1.1.14.tar.gz
./configure && make && make install
XFS:
tar xf xfsprogs_2.9.8-1.tar.bz2
./configure && make && make install
REISERFS:
tar xf reiserfsprogs-3.6.21.tar.bz2
./configure && make && make install
准备4个相同大小的分区:
mkfs.ext4 /dev/sda10
mount /dev/sda10 /1
mkfs.xfs /dev/sda11
mount /dev/sda11 /2
mkfs.jfs /dev/sda12
mount /dev/sda12 /3
mkreiserfs /dev/sda13
mount /dev/sda13 /4
/dev/sda10 ext4 972404 17608 905400 2% /1
/dev/sda11 xfs 983164 4256 978908 1% /2
/dev/sda12 jfs 983632 256 983376 1% /3
/dev/sda13 reiserfs 987868 32840 955028 4% /4
==================
如果系统中已经有EXT3,如果在不重新格式化情况下转换成EXT4?
修改 /etc/fstab
替换ext3为ext4
重启系统
==================
文件系统(ext3)
日志、数据分离
指定这个分区是记入日志
mke2fs -j -O journal_dev /dev/hda11
指定某个分区的日志记入到其他地方
mke2fs -j -J device=/dev/hda11 /dev/hda12
==============================
具体值调整,数据块1k 2k 4k
dumpe2fs /dev/hda11 | less
mke2fs -j -b 4096 /dev/hda11
块大 空间
如果存储的是小文件,那么就会浪费,速度无变化
4096 block [*** ]
如果存储的是大文件,浪费略,速度变快
[***][***][*** ]
[*][*][*][*][*][*]
块小
针对小文件
Inode数量
-i bytes-per-inode
-N number-of-inodes
数量大 在修复或检测fsck,会浪费很长时间。
数量小 将来有空间。但是不能存文件。
mkfs.ext3 -b 4096 -i 16384 /dev/sda8
mkfs.ext3 -b 4096 -N 1024 /dev/sda8
挂载:
关于EXT3控制
data=writeback,commit=30
通用:
noatime
nodiratime
async
总结:
mount -o noatime,nodiratime,async,data=writeback,commit=30 /dev/sda6 /mnt/
=============================
测试或监控工具:
iostat
-x
-k
sar -b
sar -d
如果 %util 接近 100%,说明产生的I/O请求
太多,I/O系统已经满负荷,该磁盘可能存在
瓶颈。
linux IO有关的几个参数
今天发现系统的负载比较高,检查发现硬盘根目录的io等待延时非常的大,但是读写量非常的小,打开block_dump发现kjournald(685): 845
pdflush(3196): 286,由于又是虚拟机 所以也不能确定是不是这个导致的:
pdflush 进程详解
由于页高速缓存的缓存作用,写操作实际上会被延迟。当页高速缓存中的数据比后台存储的数据更新时,那么该数据就被称做脏数据。在内存中累积起来的脏页最终必须被写回磁
盘。在以下两种情况发生时,脏页被写回磁盘:
·当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。
·当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘,以确保脏页不会无限期地驻留在内存中。
上面两种工作的目的完全不同。实际上,在老内核中,这是由两个独立的内核线程(请看后面章节)分别完成的。但是在2.6内核中,由一群内核线程—pdflush后台回写例程—统
一执行两种工作。说pdflush是“dirty page flush”的缩写是不正确的,不用去管这个让人混淆的名称,我们来看看这两个目标是如何具体实现的。
首先,pdflush线程在系统中的空闲内存低于一个特定的阈值时,将脏页刷新回磁盘。该后台回写例程的目的在于在可用物理内存过低时,释放脏页以重新获得内存。特定的内存阈
值可以通过dirty_background_ratio sysctl系统调用设置。当空闲内存比阈值:dirty_ background_ratio还低时,内核便会调用函数wakeup_bdflush()唤醒一个pdflush线程,随
后pdflush线程进一步调用函数background_writeout()开始将脏页写回磁盘。函数background_ writeout()需要一个长整型参数,该参数指定试图写回的页面数目。函数
background_writeout()会连续地写出数据,直到满足以下两个条件:
·已经有指定的最小数目的页被写出到磁盘。
·空闲内存数已经回升,超过了阈值dirty_background_ratio。
上述条件确保了pdflush操作可以减轻系统中内存不足的压力。回写操作不会在达到这两个条件前停止,除非pdflush写回了所有的脏页,没有剩下的脏页可再被写回了。
满足第二个目标,pdflush后台例程会被周期性唤醒(和空闲内存是否过低无关),将那些在内存中驻留时间过长的脏页写出,确保内存中不会有长期存在的脏页。如果系统发生崩
溃,由于内存处于混乱之中,所以那些在内存中还没来得及写回磁盘的脏页就会丢失,所以周期性同步页高速缓存和磁盘非常重要。在系统启动时,内核初始化一个定时器,让它
周期地唤醒pdflush线程,随后使其运行函数wb_kupdate()。该函数将把所有驻留时间超过百分之dirty_expire_centisecs秒的脏页写回。然后定时器将再次被初始化为百分之
dirty_expire_ centisecs秒后唤醒pdflush线程。总而言之,pdflush线程周期地被唤醒并且把超过特定期限的脏页写回磁盘。
系统管理员可以在/proc/sys/vm中设置回写相关的参数,也可以通过sysctl系统调用设置它们。
http://www.itlearner.com/article/4542
kjournald
就是为ext3文件系统提供日志服务 详细:http://hi.baidu.com/171892549/blog/item/c87ec7803d6699db9123d90f.html
查了一下发现 只有用ext2才能完全禁用kjournald,不管了 反正我数据有备份,决定尝试下 ext2在观察一下
下面是几个影响磁盘IO的系统参数:
A process that writes something to a file generates dirty pages in the page cache. Dirty pages must be kept in sync with their backing store (the file
defined on the block device).
In the Linux kernel the frequency to writeback dirty pages is controlled by two parameters: vm.dirty_ratio and vm.dirty_background_ratio. Both are expressed
a percentage of dirtyable memory, that is the free memory + reclaimable memory (active and inactive pages in the LRU list).
The first parameter controls when a process will itself start writing out dirty data, the second controls when the kernel thread [pdflush] must be woken up
and it will start writing out dirty data globally on behalf of the processes (dirty_background_ratio is always less than dirty_ratio; if
dirty_background_ratio >= dirty_ratio the kernel automatically set it to dirty_ratio / 2).
Unfortunately, both percentages are int and the kernel doesn't even allow to set them below 5%. This means that in large memory machine those limits are too
coarse. On a machine that has 1GB of dirtyable memory the kernel will start to writeback dirty pages in chunks of 50MB (!!!) minimum (with dirty_ratio = 5).
Even if it could be fine for batch or server machines, this behaviour could be unpleasant for desktop or latency-sensitive environments, when the large
writeback can be perceived as a lack of responsiveness in the whole system.
/proc/sys/vm/dirty_ratio
该文件表示如果进程产生的脏数据到达系统整体内存的百分比,此时进程自行把脏数据写回磁盘
proc/sys/vm/dirty_background_ratio
这个参数控制文件系统的pdflush进程,在何时刷新磁盘。单位是百分比,表示系统内存的百分比,意思是当写缓冲使用到系统内存多少的时候,pdflush开始向磁盘写出数据。增
大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。但是,当你需要持续、恒定的写入场合时,应该降低其数值,一般启动上缺省是 5。下面是增大的方法
:
echo '20' > /proc/sys/vm/dirty_background_ratio
/proc/sys/vm/dirty_writeback_centisecs
这个参数控制内核的脏数据刷新进程pdflush的运行间隔。单位是 1/100 秒。缺省数值是500,也就是 5 秒。如果你的系统是持续地写入动作,那么实际上还是降低这个数值比较
好,这样可以把尖峰的写操作削平成多次写操作。设置方法如下:
echo "200" > /proc/sys/vm/dirty_writeback_centisecs
如果你的系统是短期地尖峰式的写操作,并且写入数据不大(几十M/次)且内存有比较多富裕,那么应该增大此数值:
echo "1000" > /proc/sys/vm/dirty_writeback_centisecs
[编辑] /proc/sys/vm/dirty_expire_centisecs
这个参数声明Linux内核写缓冲区里面的数据多“旧”了之后,pdflush进程就开始考虑写到磁盘中去。单位是 1/100秒。缺省是 30000,也就是 30 秒的数据就算旧了,将会刷新
磁盘。对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快。建议设置为 1500,也就是15秒算旧。
echo "1500" > /proc/sys/vm/dirty_expire_centisecs
当然,如果你的系统内存比较大,并且写入模式是间歇式的,并且每次写入的数据不大(比如几十M),那么这个值还是大些的好
http://www.pgsqldb.org/mwiki/index.php/Linux%E5%86%85%E6%A0%B8%E5%8F%82%E6%95%B0