批量删除 S3 文件的最有效方法

Sud*_*ill 25 amazon-s3 batch-processing

我希望能够在 S3 上一次批量删除数千或数万个文件。每个文件的大小从 1MB 到 50MB 不等。自然,我不希望用户(或我的服务器)在文件被删除的过程中等待。因此,问题:

  1. S3 如何处理文件删除,尤其是在删除大量文件时?
  2. 有没有一种有效的方法可以做到这一点并使 AWS 完成大部分工作?高效,我的意思是向 S3 发出最少数量的请求并花费最少的时间使用服务器上最少的资源。

ant*_*tak 29

速度奇慢的选择是s3 rm --recursive,如果你真的喜欢等待。

s3 rm --recursive使用不同的--include模式并行运行会稍微快一些,但仍然需要花费大量时间等待,因为每个进程单独获取整个密钥列表以便在本地执行--include模式匹配。

输入批量删除。

我发现使用aws s3api delete-objects.

下面是一个例子:

cat file-of-keys | xargs -P8 -n1000 bash -c 'aws s3api delete-objects --bucket MY_BUCKET_NAME --delete "Objects=[$(printf "{Key=%s}," "$@")],Quiet=true"' _
Run Code Online (Sandbox Code Playgroud)
  • -P8上选项xargs控制并行性。在这种情况下是 8 个,这意味着一次 1000 个删除的 8 个实例。
  • -n1000选项告诉xargs为每个aws s3api delete-objects呼叫捆绑 1000 个密钥。
  • ,Quiet=true将其删除或更改为false会发出服务器响应。
  • 注意:_在该命令行的末尾很容易遗漏一个。@VladNikiforov 在评论中对它的用途发表了出色的评论,所以我将链接到它。

但是你怎么得到file-of-keys

如果你已经有了你的钥匙清单,那对你有好处。作业完成。

如果没有,我想这是一种方法:

aws s3 ls "s3://MY_BUCKET_NAME/SOME_SUB_DIR" | sed -nre "s|[0-9-]+ [0-9:]+ +[0-9]+ |SOME_SUB_DIR|p" >file-of-keys
Run Code Online (Sandbox Code Playgroud)

  • 很好的方法,但我发现列出密钥是瓶颈。这要快得多:`aws s3api list-objects --output text --bucket BUCKET --query 'Contents[].[Key]' | pv -l > BUCKET.keys` 然后删除对象(这足以超过 1 个并行进程达到对象删除的速率限制):`tail -n+0 BUCKET.keys | pv -l | grep -v -e "'" | tr '\n' '\0' | xargs -0 -P1 -n1000 bash -c 'aws s3api delete-objects --bucket BUCKET --delete "Objects=[$(printf "{Key=%q}," "$@")],Quiet=true" '_` (12认同)
  • 最后你可能还应该强调 `_` 的重要性:) 我错过了它,然后我花了很长时间才理解为什么第一个元素被跳过。关键是`bash -c` 将所有参数作为位置参数传递,从`$0` 开始,而"$@" 只处理以`$1` 开头的参数。所以需要下划线虚拟来填充`$0`的位置。 (5认同)
  • 我发现这种方法(来自 antak 或 Vlad)的一个问题是,如果出现错误,它不容易恢复。如果您要删除大量密钥(在我的情况下为 10M),您可能会遇到网络错误或限制错误,这会破坏这一点。因此,为了改进这一点,我使用 `split -l 1000` 将我的密钥文件拆分为 1000 个密钥批次。现在对于每个文件,我可以发出删除命令然后删除文件。如果有什么问题,我可以继续。 (4认同)
  • 如果您只想要所有键列表,我会认为 `aws s3 ls "s3://MY_BUCKET_NAME/SOME_SUB_DIR" | awk '{print $4}'` 会更简单,你可以添加一个 `| grep` 从那里过滤掉它。 (2认同)

小智 13

AWS 支持使用 S3 REST API 及其各种包装器对每个请求批量删除多达 1000 个对象。此方法假定您知道要删除的 S3 对象键(也就是说,它并非旨在处理诸如保留策略、超过特定大小的文件等)。

S3 REST API 可以在单个请求中指定最多 1000 个要删除的文件,这必须比发出单个请求更快。请记住,每个请求都是一个 HTTP(因此是 TCP)请求。所以每个请求都会带来开销。您只需要知道对象的键并创建一个 HTTP 请求(或使用您选择的语言的包装器)。AWS 提供了有关此功能及其用法的大量信息。只需选择您最满意的方法即可!

我假设您的用例涉及最终用户指定要一次删除的多个特定文件。而不是启动诸如“清除所有引用图片文件的对象”或“清除所有早于某个日期的文件”之类的任务(我认为这很容易在 S3 中单独配置)。

如果是这样,您就会知道需要删除的密钥。这也意味着用户会喜欢关于他们的文件是否被成功删除的更多实时反馈。对精确键的引用应该非常快,因为 S3 旨在尽管处理大量数据,但仍能有效扩展。

如果没有,您可以查看异步 API 调用。您可以从这篇博文中阅读一些有关它们一般如何工作的信息,或者搜索如何使用您选择的语言进行操作。这将允许删除请求占用自己的线程,并且其余代码可以执行而无需用户等待。或者,您可以将请求卸载到 queue 。. . 但是这两个选项都会不必要地使您的代码(异步代码可能很烦人)或您的环境(您需要一个服务/守护程序/容器/服务器来处理队列)复杂化。因此,如果可能,我会避免这种情况。

编辑:我没有发布超过 2 个链接的声誉。但是您可以在此处查看亚马逊对请求率和性能的评论:http : //docs.aws.amazon.com/AmazonS3/latest/dev/request-rate-perf-considers.html而 s3 faq 评论是批量删除如果可能的话,要走的路。


小智 8

一个巧妙的技巧是使用生命周期规则为您处理删除。您可以将规则排队以删除您想要的前缀或对象,亚马逊将负责删除。

https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-lifecycle.html

  • 但是要小心,因为如果您有很多对象,这可能会非常昂贵,/sf/ask/3797919331/ (2认同)

ksu*_*ton 6

带 S3API 的一班轮配料

这是我根据这篇文章的其他回复写的一句话。

  1. 获取一批 1000 个 S3 对象密钥(无需将它们保存到文件中)
  2. 通过管道将键传递给删除命令
  3. 两个删除命令并行启动,每个命令删除 500 个对象
aws s3api list-objects-v2 --bucket $BUCKET --prefix $PREFIX --output text --query \
'Contents[].[Key]' | grep -v -e "'" | tr '\n' '\0' | xargs -0 -P2 -n500 bash -c \
'aws s3api delete-objects --bucket $BUCKET --delete "Objects=[$(printf "{Key=%q}," "$@")],Quiet=true"' _ 
Run Code Online (Sandbox Code Playgroud)

为什么没有密钥文件?

关于将密钥通过管道传输到文件的抱怨之一是从 s3 删除时可能会发生错误。如果您必须重新启动删除命令,您将拥有一个包含大量已删除键的文件,并且您将浪费时间再次运行删除命令。

为什么有2个删除命令?

我尝试使用 1 个删除命令删除所有 1000 个对象。我会收到一个错误,我的参数列表太长(因为我有很长的键)


dan*_*man 5

我对 Web 控制台执行此任务的性能感到沮丧。我发现AWS CLI命令在这方面做得很好。例如:

aws s3 rm --recursive s3://my-bucket-name/huge-directory-full-of-files

对于大型文件层次结构,这可能需要相当长的时间。您可以将其设置为在tmuxscreen会话中运行,稍后再回来查看。

  • 看起来 `aws s3 rm --recursive` 命令会单独删除文件。虽然比 web 控制台快,但在删除大量文件时,如果批量删除可能会快得多 (2认同)

小智 5

前面已经提到过s3 sync命令,但没有示例和选项--delete

我发现通过以下方式删除存储S3桶中文件夹内容的最快方法my_bucket

aws s3 sync --delete "local-empty-dir/" "s3://my_bucket/path-to-clear"

Run Code Online (Sandbox Code Playgroud)