【问题标题】:GCP Storage Bucket Transfers (gsutil)GCP 存储桶传输 (gsutil)
【发布时间】:2018-11-04 01:53:51
【问题描述】:

我正在尝试使用 gsutil mv 从各种存储桶中移动 1500 万个文件 (4TB)。不幸的是,以前的文件名不共享 any 通用前缀;相反,它们都以我们的“文件类型”标识符为后缀。

在此传输过程中,我也打算重命名文件以防止将来发生这种混乱。

这是我们当前的文件格式:

gs://{bucket}/{hash}-{filetype}.{extn}

这是我将它们重命名为的格式:

gs://{bucket}/{filetype}/{hash}.{extn}

当前解决方案:

因为目前的格式不利于“前缀”选择器,所以我不得不做以下事情:

let { stdout } = spawn('gsutil', ['ls', `${OLD_BUCKET}/*-${TYPE}`]);
createInterface({ input:stdout }).on('line', str => {
  if (!str.length) return;
  let [hash] = str.replace(OLD_BUCKET, '').split('-');
  let nxt = `${NEW_BUCKET}/${TYPE}/${hash}.${extn}`;
  spawnSync('gsutil', ['mv', str, nxt]);
});

为简洁起见,略作编辑。

奇怪的是,gsutil ls 是唯一可以识别基于 glob 的模式的命令。利用这一点,我将每条线路通过管道传输到我的“格式转换器”中,然后使用gsutil mv 启动传输。

此操作在 16 核机器上运行,每个核执行相同的任务 -- 但ls'ing 使用不同的文件类型。

问题

这太慢了!

我已经投入了更多的服务器和更多的内核,而且我无法在每个文件类型每分钟破坏 26 个文件。我还尝试将-m 标志添加到gsutil mv,没有区别——因为mv 每行调用一次。

我们有 13 种文件类型;因此每小时传输 20,280 个文件。将此与 GCP 的“传输”工具进行比较,后者在不到一个小时内将 500 万个文件从 BucketA复制到 BackupA。

问题

有什么办法可以加快速度吗?

按照目前的费率,我正在等待 15 天,直到转账完成,按小时支付????

【问题讨论】:

  • 由于您的 mv 命令只是在等待 GCS 完成工作,我认为您可以在每个核心上运行超过 1 个命令。希望您可以通过这种方式实现更多并行化。
  • 你会这么想的,是的。但是每个核心运行 2 个会导致 EAGAIN 错误。这就是为什么我又启动了另外 3 台机器,每台机器有 16 个内核。即使所有 4 个服务器都在运行(每个文件类型 4 个mv),每个单独的存储桶也被限制为每分钟约 26 个文件。 AKA 在机器之间并行化负载的收益为 0。
  • 这很有趣。感谢您的评论,我去寻找人为的速率限制并找到了这些文档。 cloud.google.com/storage/docs/request-rate#ramp-up

标签: google-cloud-platform google-cloud-storage gsutil


【解决方案1】:

我对 Rust 不是很熟悉,但据我所知,使用 GCP 和 c++(例如管理),最慢的部分是等待 google 对每个操作的响应(如 gutil lsgutil mv),这样,即使在16核的机器上,大部分线程也会处于空闲状态等待google对操作的响应。

因此,您可能希望优化您所做的请求数量,并让 google 完成艰苦的工作。 (您还需要为 google 用于执行这些操作的资源付费,不包括执行请求的 VM 实例)

检查gsutil mv documentation,它说-m 将使该操作成为多线程操作(在谷歌的移动服务中),但只有在相同的请求包含多个要移动的文件时才会起作用。

文档还提到 gsutil mvgsutil cp 的扩展,它将文件复制到目标路径,然后在继承命令选项的旧路径 (gsutil cp documentation) 上执行删除。

所以我的建议是让您尝试使用Name WildCards 压缩请求,并查看gsutil cp 文档以获取您也可以设置为mv 的标志列表。

很抱歉没有发布代码答案,时间对我来说有点短。希望这可以帮助你一些方向:)

【讨论】:

  • 感谢您的帮助!我不认为mv 一次接受多个文件,只接受一个from 和一个to。这个限制很好,除了我不能内联执行文件名重写。我可以使用通配符将所有文件移动到新存储桶,但我仍然无法一次重命名一个 AFAICT。
  • gsutil 确实接受多个源文件,但它们都必须移动到一个目标目录(类似于 Unix mv 语法)。而且由于您正在更改 gsutil mv 支持对您没有帮助的每个移动的文件名。我也不熟悉生锈。 createInterface 是否在输入行上并行化?如果不是,那是你的问题。您可以改为使用 gsutil ls 创建完整的对象列表,然后在本地编辑列表(使用编辑器或 sed)以生成一系列 gsutil mv 命令。然后你可以一次运行 N 个这样的命令。
  • 是的,我对单一目的地很好。 mv *-foobar.jpg foobar/*.jpg 是所需的格式,但问题还是重命名。不知道你们俩是从哪里得到 Rust 的,但这实际上是 Node.js——createInterface 来自 readline 模块。 AKA,不,它不会并行化:P
  • 我相信@MikeSchwartz 是正确的,但如果你真的不能为每个mv 请求运行多个文件,你可以尝试获取完整列表,准备命令行来移动每个文件,然后运行每个mv cmd 在单独的线程中。您可以使用线程池,设置最大线程数来运行请求(您可以创建数千个线程,因为它们中的大多数无论如何都会休眠等待谷歌的响应),并且线程会选择新的命令来运行它们是完成,直到命令队列为空
  • 更新:我使用 Rust 编写了一个新程序,以利用更大的线程池。旧项目被抢先写入文件(在程序启动之前),然后逐行通过管道传输到 prog 中,进行转换,然后调用 gsutil mv 实例。即使使用更大的线程池,我每分钟也能获得大约 370 个文件,这仅比 Node.js 的平均值高 +40。证据与 Bucket 带宽限制相悖。
猜你喜欢
  • 2021-07-25
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-17
  • 2021-02-05
  • 2019-07-26
相关资源
最近更新 更多