经验谈:用 cp 命令复制大量文件(432,000,000个,共39TB)


英文:lists.gnu.org

译文:伯乐在线 - honpey

链接:http://blog.jobbole.com/77698/

最近,我有一个复制大量文件的需求,虽然我已经在Unix各种变种上有超过20年的工作经验,但是我仍然被cp指令的行为震撼,我认为这些心得很值得和大家分享下。


首先介绍下机器:一台戴尔服务器(双核,内存最初是2G,后来扩展到10G,运行ubuntu系统),服务器配备的是全新戴尔存储套件 MD1200,该套件包括12个4TB硬盘,其中40TB采用RAID6配置,这样整个系统就可以容忍两块硬盘同时down掉。这台服务器主要用作异地备份,唯一的操作是IO写,由于我使用rsnapshot完成这项工作, 因此大部分文件有较高的链接计数(30+)。


一天早上,我被告知一个硬盘down掉了。这不是什么大事,这种事情经常发生。我打电话给戴尔,戴尔第二天就给送来了一块替换盘。但我安装替换盘时发现,替换盘根本不能工作,并且另一块磁盘也down掉了。戴尔技术服务部门富有经验地建议我不要只换down掉的硬盘,因为整个磁盘阵列可能已经损毁了。就我所知,磁盘只有在有足够多坏块的情况下才会告警,设想这样一个场景:短时间内,一个文件位于三个磁盘上的备份块全部坏掉,那么很不幸,RAID引擎短时间内难以完成检测坏块、重新计算备份数据并存储这样一个流程,这样你就有丢失数据的风险了。因此,如果两个硬盘显式告警,你的数据可能已经丢失了。


现有存储套件容量已经难以达到要求,我们决定扩容,把文件从旧存储套件拷贝到新套件中。正常情况下,我会在块级别拷贝用dd指令或者pvmove指令拷贝数据,但是考虑到坏块,我决定采用文件级别的拷贝,因为这样的话,我就可以知道那些文件包含坏块了。我上网搜了相关经验,发现cp可以完美地解决这个问题。若想保存硬链接信息,需要记录有哪些文件已经被复制,所以我预订了8G的RAM,并配置了更大的交换区。


当新的存储套件到货,我就着手复制了,起初,根据iotop的测量数据,复制速度接近于300-400MB/s。不一会儿速度便显著下降了,因为大 部分时间花在了建立硬链接上,并且要花时间去处理文件系统的一致性问题。为保持一致性,我们使用了XFS,由于没有关闭写屏障,我们深受性能之苦,但如果RAID控制器配置了带有备份电源的写缓存,一致性问题便可更好地解决。正如所料,cp的内存占用量稳步增加,很快便达到了GB级。


经历了几天的拷贝,问题来了:我发现系统已经停止拷贝,根据strace的显示,cp指令没有调用任何的系统调用函数。阅读相关源码后发现,cp指令会以一个哈希表跟踪有哪些文件被复制了,这个表需要时常地扩展自身容量以避免太多的冲突。当RAM被耗尽,哈希表的扩容过程会成为性能瓶颈。


我们相信cp的哈希表扩容后,cp指令会继续执行,果然不一会它又“复活”了,但是它会进入周期性的“扩容-拷贝-扩容-拷贝”的循环中,且扩容的 时间变得越来越长。经过10天的拷贝,根据dd结果,新文件系统的块数量和inode节点的数量已经和原系统一样,但是让人吃惊的是cp指令并没有退出。


再次阅读源码,我发现cp正在认真地解构哈希表(使用forget_all函数),由于cp进程需要的虚拟内存大小达到了17GB+,但服务器总共才10G内存,所以解构过程执行了很多RAM和swap区间的换页操作。


上面整个过程中,我使用了cp的-v选项,并使用tee把日志重定向到日志文件(很大的文件)中。cp的输出信息会被缓存,为使这些缓存信息全部刷新到日志文件中,我给了cp多于一天的时间进行解构哈希表。


运行”ls �laR”指令,查看下两个文件系统中的文件是否一致,发现除了日志文件的一些错误外,只有一个文件发生了io错误(还好,我们有它的另一个备份)。


这种错误不会马上复现,但是如果cp能够设计一种数据结构,在等待io的时候处理那些已经被记录的文件,那样处理效率会更高。此外,对于cp最后解 构哈希表的forget_all函数,除了那些缺少可用内存管理模块的老式服务器一定需要它之外,我还没发现去掉这个函数会对整个拷贝过程产生什么不好的影响。


总结一下:


1、拷贝整个文件系统时,如果确定你的硬件和文件系统都OK,应该使用块级别的拷贝。这种拷贝方式更快,除非你有许多空闲块,但是无论如何它耗费的内存都是较少的;


2、如果要拷贝许多文件,并想要保留硬链接的信息,可以采用文件级拷贝。拷贝之前需要保证机器有足够多的内存;


3、比起简单粗暴地停止进程,认真地解构数据结构会花费更多的时间;


4、告警的硬盘的数量并不等同于有坏块的硬盘的数量。如果不走运,就算配置了RAID6,没来得及等3块磁盘告警,你的数据可能已经丢失。这个时候我们只能赌一把了。同样的情况适用于RAID 5,那怕只有一块磁盘甚至没有磁盘告警,如果不走运,你的数据照样丢!



你可能感兴趣的:(ubuntu,工作经验,在线,经验谈,戴尔服务器)