编程实现虚拟RAID读磁盘并发
从事企业级数据恢复不可避免的需要对大量磁盘在软件层实现虚拟RAID,并对此进行操作,目前可实现虚拟RAID的常用数据恢复软件如:WinHex、R-Studio、UFS explorer 等虽可以实现虚拟RAID,但实际上虚拟RAID并没有并发线程,也就是说,虚拟RAID最快速度也只是单块磁盘的速度,如果虚拟RAID中磁盘数量较多,做某些操作时,时间成本将大大提高。自己进行的某些项目,也实现了虚拟RAID功能,但和WinHex、R-Studio、UFSexplorer等软件一样,操作磁盘也没有使用并发,原因一方面是代码不好设计,调试麻烦,另一方面也不想在此浪费时间,能实现功能就行,对于规模不大的虚拟RAID,时间也可以接受。
前些时间因为一个单子,最后还是决定实现虚拟RAID的并发功能。
那个单子是一个28块1TB磁盘做的RAID5,因为文件系统特殊,需要在软件层重组虚拟RAID,并对其进行镜像,磁盘数量较多,winhex 不支持,其它软件也不支持镜像到磁盘,最后只得在自己的软件上添加克隆功能进行镜像。由于软件没有虚拟RAID的并发功能,镜像速度也只相当于一块磁盘的速度,而源盘型号较垃圾,速度慢,镜像速度只有一分钟6-7GB,此RAID需要镜像的空间超过20TB,镜像时间超过2天。客户还是在外地,上门工作,使得经济成本大大提高。
目前在做的项目已实现了虚拟RAID的并发功能,实测用3块磁盘(每块磁盘最高速度约11 -12GB每分钟) 的做的虚拟RAID0,读速度达到34GB每分钟; 同样的介质做成虚拟RAID5后,读速度达到23GB每分钟。当然,如果是做镜像或是解析文件系统进行数据导出的话,还要看目标介质的写入速度了。
问题:影响虚拟RAID 速度的因素
1:RAID 块大小。
2:读磁盘速度。
RAID 块大小因素:
解决思路:
如果RAID块大小为1扇区,如果一次请求1024个扇区。一般思路:一个块一个块的读,此次请求需要执行1024次I/O 操作,这将对速度有致命影响,WinHex、R-Studio、UFS explorer等软件对于此种情况,速度下降10倍以上。
解决方案:通过请求的开始扇区号和要读取的扇区数,计算出每块磁盘在此次请求中要读取的开始扇区和扇区数,这样对每块磁盘只进行一次I/O 操作,然后在内存中重新按RAID格式组织缓冲,返回。
如果RAID块大小为2048扇区,如果一次请求1024个扇区,一般情况下这次请求的扇区都在一个块内,也就是说只需从一块磁盘中读取,并发无作用,速度是单块磁盘的速度。这种情况只有通过提高要读取的扇区数来解决。
读磁盘速度因素:
解决思路:
如果一次请求1024扇区,RAID块大小为128扇区,此次请求最少需要操作8个块,如果这个8 个块分布在8 个磁盘上,则需要读取8个磁盘。WinHex、R-Studio、UFSexplorer软件的思路:读1号磁盘->读1号磁盘完成->读2号磁盘->读2号磁盘完成->读3号磁盘…
此方法较好控制,软件不容易出错。如果使用并发,此次请求的时间将为原来时间的1/8(理论上),就是同时创建8个线程,每个线程读一块磁盘,待8个线程执行完成,再进行缓冲整理,返回。当然也可以8个线程进行缓冲整理,但缓冲整理所需时间很少,不是影响速度的因素。
下面是伪代码:
自定义函数 isREAD_DiskC// 判断所需磁盘是否读完,此函数要使用线程互斥,同时只
// 能一个线程使用,否则读完磁盘计数的变量数据容易被覆盖
Begin
读完磁盘计数的全局变量+1;
如果 (读完磁盘计数 = 这次请求要读的磁盘数) 就
继续主控制线程:Main_control;
关闭当前线程;
End;
自定义函数 RAID_READ_DISK(read_parameters)// 每个线程读磁盘的函数
Begin
根据结构体指针 read_parameters 中的数值读取磁盘扇区数据; // read_parameters 记录要读的磁盘介质,
//开始扇区号,要读的扇区数,所读到的缓冲地址
读完后关闭此单个磁盘的读线程;
创建一条线程执行 isREAD_DiskC 函数;
End;
自定义函数 Main_control ////// 主控制线程
Begin
通过请求的开始扇区号和扇区数 用 自定义函数:GetNeedSectorInfo 得到要读的磁盘列表和取出每块磁盘要读的开始扇区和扇区数;
循环要读的磁盘数量
Begin
read_parameters := 此块磁盘 GetNeedSectorInfo函数中得到的值;
创建一条线程 执行RAID_READ_DISK(read_parameters);
End;
执行Main_control 函数的线程挂起,等待自定义函数isREAD_DiskC 的指令继续;
要读的磁盘全读完后,缓冲整理过程 ......;
End;
实际上使用并发,代码量不会多多少,只是线程难以准确控制,也不好调试。
这其中要注意缓冲数据覆盖和全局控制变量的一致性,特别是在虚拟RAID中有成员为另一个虚拟RAID的时候。 good~~~~~~~~~~~ 哇,好东西啊!!! 一直纠结于这个速度,借此试试!! 厉害,膜拜了 学習了~非常感謝! 如果仅仅是复制一些特定后缀的文件 两个USB口分别对应组成RAID0的两块硬盘 并行写入的时候如何确定写入的位置呢? 是不是自己要添加MFT表中的记录? 问题来了 添加记录的话 如何确定添加记录的位置呢? 很好 我很喜欢 很好 我很喜欢 真厉害,太深了
页:
[1]
2