我经常需要在服务器之间或向 aws s3 传输数百万个小文件(小图像、txt、json),平均每个文件 5-50k。
除了 zip/tar -cf 之外,是否有更快的方法将它们合并到单个文件中以优化传输速度?
答案1
类似的东西tar cz * | ssh <host> "tar xfc -"
?说真的,有什么问题吗tar
?此命令不会创建任何中间文件。
答案2
从其他答案中发展想法,您可以通过管道发送信息,甚至不在本地创建文件tar
。命令将类似于:
tar cf - * | aws s3 cp - s3://some-bucket/archive.tar
该命令的优点是可以并行运行tar
和aws
命令。您甚至可以添加压缩(这将再次并行执行)
tar cf - * | gzip -c | aws s3 cp - s3://some-bucket/archive.tar.gz
为了简化操作,您可以使用文件的顶级目录而不是使用*
:
tar cf - top_level_directory | aws s3 cp - s3://some-bucket/archive.tar
tar cf - top_level_directory | gzip -c | aws s3 cp - s3://some-bucket/archive.tar.gz
受到其他答案的启发,您可以使用cpio
。似乎更快并且生成更小的文件:
ls |cpio -o |gzip -c | aws s3 cp - s3://some-bucket/archive.cpio.gz
答案3
是的,有很多选择。
一是永远不要创建中间文件,正如其他答案中所建议的那样。这会减少本地 IO,但无法恢复部分上传。
还有其他选项可以进一步改进:
- 对存档使用压缩。 GZip 是经典的,但它有点慢。 LZ4 如今已相当广泛使用,速度极快,并且仍然可以为您提供不错的压缩比
tar
以及您所描述的内容。 ZSTD 的速度不如 LZ4,但会在更短的时间内获得与 GZip 类似的压缩率。无论选择如何,这都可能会显着减少要传输的总数据量。 - 考虑使用
cpio
而不是tar
.tar
不完全是一种节省空间的存档格式。这通常没什么关系,但是如果您正在处理数百万个非常小的文件,那么开销实际上是相当大的。cpio
仍然有相当大的开销,但它比tar
实际要少,因此理论上cpio
在这里使用应该会导致要传输的数据量显着减少。 - 考虑创建多个档案,每个档案包含文件的子集(例如,每个档案中可能不超过 100k 个文件),然后并行上传这些档案。假设源系统具有快速的互联网连接和相对较快的存储,这(几乎肯定)会比上传一个大档案更快,因为它可以更好地并行化本地 IO(并且因为 AWS 也可以在其端并行处理事物)。这里的“最佳”大小通常足够小,您不需要使用分段上传。即使您跳过在本地创建中间文件,这也有助于恢复部分上传,因为您只需上传尚未上传的档案。
答案4
我使用的是 rclone 的大量多线程使用。我在服务器和 S3 之间做了类似的事情。