繁体   English   中英

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

[英]AWS S3 client race condition solutions

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

关于工程师如何使用他们的 s3 客户端实现锁定机制的一些建议将不胜感激。

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

嗯……您现在将与锁定文件发生竞争状况……多个节点将上传相同的锁定文件!

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

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

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

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

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

我认为你有两个选择:

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

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

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

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

工作环境文档

如果您不想使用 AWS 特定技术(例如 SQS 或 lambdas),您有 2 个选项:

现有数据库

如果您有一个可以利用的现有数据库,您可以使用咨询锁(例如 Postgres 提供的),如下所示: 当一个进程想要处理文件时:

  1. 它首先检查锁是否可用。 如果没有,它将不得不等待锁定。
  2. 一旦它获得锁,它就可以做它需要的工作,包括删除文件。
  3. 它最终释放了锁。

从概念上讲,这与您提到的.lock文件设置非常相似。

使用外部服务

类似lockable的东西。 如果你使用 Python,你可以使用他们的Python 客户端

$ pip install lockable-dev

from lockable import Lock

with Lock('my-lock-name'):
    #do stuff

如果你不使用 Python,你仍然可以使用他们的 HTTP 端点; 就像是

  1. curl https://api.lockable.dev/v1/acquire/my-s3-file-lock
  2. 处理文件
  3. curl https://api.lockable.dev/v1/release/my-s3-file-lock

我会尝试将文件移动到暂存桶。 只有一个过程会成功,其他过程会失败。 成功的拿下工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM