【问题标题】:AWS S3 client race condition solutionsAWS S3 客户端竞争条件解决方案
【发布时间】:2017-08-21 19:00:52
【问题描述】:

我和我的团队一直试图解决的问题涉及多个 ec2 实例,每个实例都有自己独立的并行访问同一个 S3 存储桶的权限。 当每个客户端都尝试在上述 s3 存储桶中下载相同的文件时,此问题会作为竞争条件出现。每个客户端都试图读取文件,运行一些业务逻辑,然后删除文件。由于延迟的机会很多,因此会出现竞争条件,并且多个实例最终会运行业务逻辑。

对于工程师如何使用他们的 s3 客户端实现锁定机制,我们将不胜感激。

我们集思广益的方法: 将 .lock 文件上传到 s3 存储桶,其中包含有关当前持有锁的实例的信息。当持有锁的实例完成进程时,它会删除它的锁。 (上载锁定文件时会出现问题 - 锁定机制的竞争条件)。

【问题讨论】:

标签: java amazon-s3 race-condition


【解决方案1】:

hmmm...您现在将面临与锁定文件的竞争条件...多个节点将上传同一个锁定文件!

所以你需要一些更复杂的东西,因为 S3 没有内置任何并发,这可能很不方便。

解决这个问题的明显方法是使用 SQS(简单队列服务) - 这是为并发而构建的。

因此,在您的情况下,所有节点都连接到同一个队列,等待队列中的工作。某些东西或其他东西会将元素添加到 s3 中需要处理的每个文件的队列中。其中一个节点将拾取队列中的条目,处理文件,删除文件并删除队列中的条目。

这样您就不会获得多处理,而是获得优雅的缩放等。

然而,悬而未决的问题是首先扫描 s3 以将工作放入队列中。这可能是您遇到困难的地方。

我认为你有两个选择:

  1. 使用 lambda。这是相当优雅的。您可以将 lambda 配置为在将某些内容添加到 S3 时触发。然后,此 lambda 将注册一个指向队列中文件的指针,以供 ec2 实例处理。

    lambda 的问题是您的应用程序更加分散。也就是说,您不能只查看行为代码,还必须查看 lambda。虽然我猜这个 lambda 并不是特别重量级的。

  2. 让所有 ec2 实例监控 s3,但当它们找到工作要做时,它们会将工作添加到 FIFO 队列中。这是来自 AWS 的一种相对较新的队列类型,您可以在其中保证订单并且只进行一次处理。这样可以保证即使多个节点找到同一个s3文件,也只有一个节点会处理它。

【讨论】:

  • 我认为涉及 lambda 的解决方案是最好的路线。它将使我们的应用程序更加分散,尽管它已经是。我从来没有使用过lamda。您将如何使用 lambda 来创建队列并告诉 ec2s 从所述队列中拉出?
  • 看看 SQS Java SDK - 它提供了访问队列等所需的所有方法。对于 lambda,如果你能找到预先存在的 lambda,我不会感到惊讶完全满足您的需要 - 将 s3 对象位置放入队列中。
  • 您可以直接从 S3 事件触发 lambda,例如在上传或修改时。请记住,Lambda 具有处理(主要与内存相关)和时间限制(最长持续时间 300 秒)。此外,如果您将使用一个 RDS 实例,还需要额外的配置以允许 lambda 连接到 RDS 实例。
  • 你写道:“多个节点要上传同一个锁文件” 但是只有一个会成功...所以不需要SQS。
【解决方案2】:

如果您当前的设置和应用程序可行,我会考虑将事件配置到 S3 存储桶,将消息发送到 SQS 队列(例如上传文件时),然后使用 ElasticBeanstalk Worker 环境使用队列中的消息,以便根据您的应用程序处理这些文件。

Worker Environments Docs

【讨论】:

  • 这肯定有一个坚实的基础,但是,我认为使用 lambda 函数来处理 s3 通信和排队会更好
  • Lambdas 是处理 s3 事件的好方法,我没有将它们包括在内的唯一原因是我的回答是 @ChadVanDeHey,提到他们已经实现了他们的解决方案(至少处理部分) 在 EB 中,因此切换到 EB Worker 比将其代码迁移到 lambda 更简单。
【解决方案3】:

我会尝试将文件移动到临时存储桶。 只有一个过程会成功,其他过程会失败。 成功者胜任。

【讨论】:

    猜你喜欢
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-13
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    相关资源
    最近更新 更多