AWS S3客户端竞争条件解决方案

时间:2017-08-21 19:00:52

标签: java amazon-s3 race-condition

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

对于工程师如何使用s3客户端实现锁定机制,我们将非常感谢一些建议。

我们的头脑风暴方法: 将.lock文件上传到s3存储桶,其中包含有关当前持有锁的实例的信息。当持有锁的实例完成该过程时,它将删除其锁。 (上传锁文件时出现问题 - 带锁定机制的竞争条件)。

3 个答案:

答案 0 :(得分:2)

嗯...嗯......现在你的锁文件会出现竞争状态......多个节点将上传相同的锁文件!

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

处理此问题的显而易见的方法是使用SQS(简单队列服务)   - 这是为并发而构建的。

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

这样你就不会得到多重处理,你可以获得优雅的缩放等。

然而,突出的问题是首先扫描s3以便将工作放在队列上。这可能是你出现困难的地方。

我认为你有两个选择:

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

    lambda的问题是你的应用程序有点分布。即你不能只看代码的行为,你也必须看看lambda。虽然我猜这个lambda不是特别重量级。

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

答案 1 :(得分:1)

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

Worker Environments Docs

答案 2 :(得分:0)

我会尝试将文件移至暂存区。 只有一个过程将成功,其他过程将失败。 成功承担工作的人。