前言
最近打包更新总是特别慢,其中有一步使用md5sum
命令计算MD5值的操作有时居然要卡一个小时,虽说计算MD5比较耗时,但通常计算5个G数据的md5值也就1分多钟,卡一个多小时有点说不过去了,所以在卡顿时使用 top
命令查看了进程情况,发现md5sum进程在卡顿时总是处于 D
状态,这个还是第一次遇到,所以查了些资料记录一下。
D状态进程
D 状态进程(TASK_UNINTERRUPTIBLE),处于不可中断的睡眠状态,指进程不响应异步信号。
绝大多数情况下,进程处在睡眠状态时,总是应该能够响应异步信号的。而D状态存在的意义就在于,内核的某些处理流程是不能被打断,比如进程调用read系统调用对某个设备文件进行读操作,一般需要使用D状态对进程进行保护,以避免进程与设备交互的过程被打断,造成设备陷入不可控的状态。这种情况下的D状态总是非常短暂的,通过ps命令基本上不可能捕捉到。
但是我捉到了,在执行md5sum命令时经常捉到,D状态往往是由于 I/O 资源得不到满足,而引发等待~
这是个关键点,既然IO得不到满足就查一下IO,计算md5也就从磁盘上读一些文件,所以怀疑问题出现在磁盘的读写上,进而想测一些磁盘的读写速度,这就用到了今天想说的 dd
命令。
dd命令
磁盘的读写速度需要通过实际读写文件来测试,dd
命令就可以完成这种测试,配合 time
命令可以统计命令执行时间
-
仅测读取速度
# time dd if=/tmp/test of=/dev/null bs=16k 1000000+0 records in 1000000+0 records out 16384000000 bytes (16 GB) copied, 42.7044 s, 384 MB/s real 0m42.718s user 0m0.387s sys 0m8.951s
-
仅测写入速度
# time dd if=/dev/zero of=/tmp/test bs=16k count=1000000 1000000+0 records in 1000000+0 records out 16384000000 bytes (16 GB) copied, 35.7006 s, 459 MB/s real 0m38.428s user 0m0.356s sys 0m12.608s
-
测试读写速度
# time dd if=/tmp/test of=/tmp/test2 bs=16k 1000000+0 records in 1000000+0 records out 16384000000 bytes (16 GB) copied, 87.3214 s, 188 MB/s real 1m27.331s user 0m0.430s sys 0m15.799s
问题原因
最后测试发现硬盘读写速度不是很稳定,找运维沟通发现这台服务器使用的网络硬盘,存储带宽有限,当执行太多磁盘任务时,存储带宽会被占满,会造成硬盘读写缓慢,进而影响了之前提到的计算MD5的操作步骤,换了块本地硬盘就好了。
总结
- 进程显示D状态时处于不可中断的睡眠状态,往是由于 I/O 资源得不到满足而引发了等待
- 仅测试写入速度
time dd if=/dev/zero of=/tmp/test bs=16k count=1000000
- 仅测试读取速度
time dd if=/tmp/test of=/dev/null bs=16k
- 测试读写速度
time dd if=/tmp/test of=/tmp/test2 bs=16k
/dev/zero
是一个特殊的文件,当你读它的时候会得到无限的空字符,可用来初始化文件,不产生IO/dev/null
也是一个特殊的文件,它丢弃一切写入其中的数据,被称为黑洞,也不产生IO- 网络硬盘受存储带宽的影响,一旦带宽被打满,硬盘读写速度也就慢了
好像遥不可及,但突然有那么一瞬间又感觉触手可及,貌似也没什么退路,只有往前冲了