移动 2TB(1000 万个文件 + 目录),我的瓶颈是什么?

移动 2TB(1000 万个文件 + 目录),我的瓶颈是什么?

背景

空间不足/home/data需要/home/data/repo转至/home/data2

/home/data/repo包含 1M 个目录,每个目录包含 11 个目录和 10 个文件。总计 2TB。

/home/data在 ext3 上启用了 dir_index。 /home/data2在 ext4 上。运行 CentOS 6.4。

我认为这些方法很慢,因为repo/其下方有 100 万个目录。


尝试 1:mv速度很快,但被打断了

如果这件事完成了,我就可以完成了:

/home/data> mv repo ../data2

但在传输了1.5TB之后就中断了。写入速度大约为1GB/分钟。

尝试 2:rsync在构建文件列表 8 小时后进行爬取

/home/data> rsync --ignore-existing -rv repo ../data2

花了几个小时来建立“增量文件列表”,然后以 100MB/分钟的速度传输。

我取消它以尝试更快的方法。

尝试 3a:mv抱怨

在子目录上测试它:

/home/data/repo> mv -f foobar ../../data2/repo/
mv: inter-device move failed: '(foobar)' to '../../data2/repo/foobar'; unable to remove target: Is a directory

我不确定这是关于什么的错误,但也许cp可以帮助我摆脱困境。

尝试 3b:cp8 小时后无果

/home/data> cp -nr repo ../data2

它读取磁盘 8 个小时,我决定取消它并返回 rsync。

尝试 4:rsync在构建文件列表 8 小时后进行爬取

/home/data> rsync --ignore-existing --remove-source-files -rv repo ../data2

我以前--remove-source-files认为如果我现在开始清理,可能会更快。

建立文件列表至少需要 6 个小时,然后以 100-200MB/分钟的速度传输。

但是服务器一夜之间负载过大,我的连接被关闭了。

尝试 5:只剩下 300GB 需要移动,为什么这么痛苦

/home/data> rsync --ignore-existing --remove-source-files -rvW repo ../data2

再次中断。这-W似乎让“发送增量文件列表”变得更快,但在我看来这毫无意义。无论如何,传输速度非常慢,我放弃了这个。

尝试6:tar

/home/data> nohup tar cf - . |(cd ../data2; tar xvfk -)

基本上尝试重新复制所有内容,但忽略现有文件。它必须浏览 1.7TB 的现有文件,但至少它的读取速度为 1.2GB/分钟。

到目前为止,这是唯一能立即获得满足的命令。

更新:再次中断,不知何故,即使使用 nohup...

尝试 7:切腹

仍在讨论这个问题

尝试 8:脚本“合并”mv

目标目录有大约 120k 个空目录,因此我运行

/home/data2/repo> find . -type d -empty -exec rmdir {} \;

Ruby 脚本:

SRC  = "/home/data/repo"
DEST = "/home/data2/repo"

`ls #{SRC}  --color=never > lst1.tmp`
`ls #{DEST} --color=never > lst2.tmp`
`diff lst1.tmp lst2.tmp | grep '<' > /home/data/missing.tmp`

t = `cat /home/data/missing.tmp | wc -l`.to_i
puts "Todo: #{t}"

# Manually `mv` each missing directory
File.open('missing.tmp').each do |line|
  dir = line.strip.gsub('< ', '')
  puts `mv #{SRC}/#{dir} #{DEST}/`
end

完毕。

答案1

听说过将大任务拆分为较小的任务吗?

/home/data/repo 包含 1M 个目录,每个目录包含 11 个目录和 10 个文件。总计 2TB。

rsync -a /source/1/ /destination/1/
rsync -a /source/2/ /destination/2/
rsync -a /source/3/ /destination/3/
rsync -a /source/4/ /destination/4/
rsync -a /source/5/ /destination/5/
rsync -a /source/6/ /destination/6/
rsync -a /source/7/ /destination/7/
rsync -a /source/8/ /destination/8/
rsync -a /source/9/ /destination/9/
rsync -a /source/10/ /destination/10/
rsync -a /source/11/ /destination/11/

(...)

咖啡休息时间。

答案2

事情是这样的:

  • 最初 rsync 将构建文件列表。
  • 由于文件列表的初始排序,构建此列表非常慢。
  • 可以通过使用 ls -f -1 并将其与 xargs 结合用于构建 rsync 将使用的文件集,或者将输出重定向到具有文件列表的文件来避免这种情况。
  • 将此列表而不是文件夹传递给 rsync,将使 rsync 立即开始工作。
  • 这篇文章完美地描述了对包含数百万个文件的文件夹使用 ls -f -1 的技巧:http://unixetc.co.uk/2012/05/20/large-directory-causes-ls-to-hang/

答案3

即使 rsync 很慢(为什么它很慢?也许 -z 会有所帮助)听起来你已经将很多内容移走了,所以你可以继续尝试:

如果您使用了--remove-source-files,那么您可以随后删除空目录。--remove-source-files 将删除所有文件,但将目录保留在那里。

只要确保你不要使用 --remove-source-files 与 --delete 进行多次传递。

另外为了提高速度,您可以使用--inplace

如果您因为尝试在服务器上远程执行此操作而被踢出,请继续在“屏幕”会话中运行此操作。至少这样您可以让它运行。

答案4

难道这不能通过结合使用 rsync 和 --inc-recursive 开关以及 cron 来实现吗?

即使是千兆位连接,移动 2 TB 也需要几个小时,没有任何开销。Rsync、mv 或 cp 都会给 I/O 增加不同程度的开销,尤其是在进行校验或其他验证时。

至少使用 --inc-recursive 开关,传输可以在文件列表仍在构建时开始。

我被告知 --inplace 可以提高速度并减少目标所需的空间,但会稍微降低文件完整性——如果不是这样的话,我很想知道。

如果随后使用适当的 rsync 设置(以及挂载远程卷所需的任何设置)创建了 cron 作业,则可以将其设置为最长运行 5:58h(使用 --stop-after=358),并且 cron 可以每 6 小时启动一次。这样,如果它随机停止,它将自动重新启动。--remove-source-files 可以与 rsync 一起使用,并且可以首先使用 find 来删除空的源目录(也许将 rsync 运行时间减少到 5:50h 以允许 find 遍历所有目录)。

我知道 rsync 的速度较慢(根据 OP),但在我看来,这样文件损坏的风险较低。

(坦白说 - 我仍在学习,所以如果我偏离了基础,请尽量温和地告诉我……)

相关内容