jes*_*ier 3 linux bash rsync multithreading
Rsync 是我们进入 Linux 后首先学习的东西之一。我一直用它来移动文件。
\n在我目前的工作中,我们管理着 PB 级的数据,并且每天都必须不断移动大量数据。
\n我看到一个名为 的源文件夹,a/其中包含 8.5GB 的数据,以及一个名为的目标文件夹b/(a 是远程安装,b 是计算机本地的)。
我的简单命令花了 2 分钟多一点:
\nrsync -avr a/ b/\nRun Code Online (Sandbox Code Playgroud)\n然后,我发现通过执行以下多线程方法,花费了 7 秒:(在本示例中使用了 10 个线程)
\ncd a; ls -1 | xargs -n1 -P10 -I% rsync -ar % b/\nRun Code Online (Sandbox Code Playgroud)\n由于巨大的时间效率,每次我们必须将数据从一个地方复制到另一个地方(几乎每天都会发生),我需要过度设计一个简单的 rsync,以便它能够将 rsync 与多线程类似到上面的第二个例子。
\n这一部分是关于为什么我不能每次都使用上面的例子,可以跳过。
\n我必须过度设计它的原因,以及我不能每次都这样做的原因cd a; ls -1 | xargs -n1 -P10 -I% rsync -ar % b/,是因为文件夹结构的情况如下:
jeff ws123 /tmp $ tree -v\n.\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 a\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 b\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 c\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file1\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file2\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file3\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file4\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file5\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file6\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file7\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file8\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file9\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file10\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file11\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file12\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file13\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file14\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file15\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file16\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file17\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file18\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file19\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 file20\nRun Code Online (Sandbox Code Playgroud)\n有人告诉我,由于a/其中只有一件事 ( b/),因此它实际上不会使用 10 个线程,而是 1 个线程,因为其中只有 1 个文件/文件夹。
我开始感觉我 40% 的工作就是在制作针对具体情况的“高效”rsync 上绞尽脑汁,而我只是觉得我做的一切都是错的。理想情况下,我可以做类似的事情rsync source/ dest/ --threads 10,让 rsync 完成艰苦的工作。
我是否以错误的方式看待这一切?有没有一种简单的方法可以在单行中使用多线程复制数据,类似于上面行中的示例?
\n谢谢阿赫德!
\n如果几乎所有文件都非常大,您可以尝试以下操作来更好地利用极快的网络:
( cd a/ && find . -type f -print0 | xargs -0 -P10 -I% rsync -avR % ../b/; )
Run Code Online (Sandbox Code Playgroud)
这里我们使用cd a/and -R/--relative来保留路径。因为cd我们必须适应相对路径b/。
但是,如果也有很多小文件,这很可能会比rsync -a a/ b/我们为每个小文件启动一个新进程慢。此外,这不适用于“--delete因为find无法列出已删除的文件”等选项。
因此,一般来说,我建议首先并行传输大文件,然后rsync对小文件和可选的文件运行最后一次,例如--delete:
( cd a/ && find . -type f -size +1G -print0 | xargs -0 -P10 -I% rsync -avR % ../b/; )
rsync -av a/ b/
Run Code Online (Sandbox Code Playgroud)
为了使其更可用,您可以编写函数或脚本。这也处理src和之间的差异src/,并允许在 后添加其他选项dest。
用法示例:prsync src/ dest/ -v --delete
#! /bin/bash
isremote() {
[[ "${1%%/*}" == *: ]]
}
prsync() {
local src="$1" dest="$2"
shift 2 || { echo "missing arguments" >&2; return 1; }
isremote "$src" && { echo "cannot handle remote source" >&2; return 1; }
(
isremote "$dest" || [[ "$dest" == /* ]] || dest="$PWD/$dest"
[[ "$src" == */ ]] || dest="$dest/${src##*/}"
cd "$src" &&
find . -type f -size +1G -print0 |
xargs -0 -P10 -I% rsync -aR "$@" % "$dest";
) &&
rsync -a "$@" "$src" "$dest"
}
Run Code Online (Sandbox Code Playgroud)
为了加快速度,请考虑添加--max-size=1G到最后一个rsync. 但是,这可能很危险,因为我不知道是否find -size +1G使用rsync --max-size=1G相同的“大小”概念,特别是对于稀疏文件和压缩文件系统。