我正在考虑使用“锁定”S3对象,以防止在给定的S3对象上同时进行相同的操作。但我非常怀疑这种技术解决方案的有效性。
更准确地说,在对对象的操作开始时,将创建对应于对象名和正在进行的操作类型的锁定文件。
示例:在myObject上的myOperation开始时,将查找lck/myObject/myOperation对象,如果该对象不存在,则创建该对象。
这个“锁”对象将在操作结束时被销毁,无论操作是否成功。
我知道标准的解决方案是使用数据库,但是应用程序目前没有数据库,因此,如果我可以只处理与S3的一致性,这就足够了。
我担心的是这个锁对象系统将在多线程/和可能的多节点架构中运行。现在,我已经了解到Amazon S3支持“写后读一致性”。
这是否意味着,如果我的应用程序1(节点1)/线程2通过Java Amazon S3 API将锁对象放在给定的存储桶上,则使用相同API的其他线程和其他应用程序将立即看到该锁对象?
4条答案
按热度按时间w41d8nur1#
不,很遗憾不会。从S3一致性模型来看:
一个进程向Amazon S3写入一个新对象,并立即列出其bucket中的键,直到更改完全传播,该对象才可能出现在列表中。
以及:
Amazon S3目前不支持对象锁定。如果同时对同一个键发出两个PUT请求,则时间戳最晚的请求优先。如果这是一个问题,您需要在应用程序中构建一个对象锁定机制。
因此,如果你的两个线程或进程都试图在S3中创建锁,它们将被允许,但最后一个写操作获胜,所以你还没有真正锁定任何东西。
vhipe2zx2#
通常情况下,我会建议使用数据库,但您提到在这种情况下这不是一个选项。
作为一种选择,你可以使用lockable这样的锁,它们提供了建议锁,可以用来控制资源访问,就像你的例子一样。
该解决方案必须使用它们的HTTPS端点(据我所知,它们只有一个Python客户端):
pcrecxhr3#
这也让我有点困扰,当时使用数据库是不可行的,所以我们想出了https://github.com/jfstephe/aws-s3-lock,这是一个javascript实现,但如果需要的话,可能会启发java版本。
dvtswwa34#
如果您在2023年来到这里,仍然认为使用S3进行锁是一个好主意,那么由于增强的一致性模型,这 * 是 * 可能的,因为它可以保证无竞争条件,并且在锁获取期间没有任何强制等待期。
1.确定锁的基名(例如
some-dir/interesting-object.lock
)some-dir/interesting-object.lock.<uuid>
。<uuid>
可以为每个锁生成,也可以为每个writer生成一次(我们假设一个writer不并发写),这无关紧要。1.列出前缀为
some-dir/interesting-object.lock.
的对象1.检查具有“我们的”UUID的文件是否是每个
ModifiedTime
中最旧的。在两个ModifiedTime
相等的极不可能的情况下,根据UUID的字典顺序断开连接。1.如果上面提到的检查成功了,你就获得了锁,你现在可以做这项工作了。否则,有人会抢在你前面。
1.删除锁定文件(注意:这意味着,如果采集失败,您应立即删除锁定文件)。
这样做是因为它保证了一旦put成功,它会立即出现在list调用中,每个工作者都会在put之后列出列表,即使另一个写入者在我们之后一纳秒写入对象,他们仍然可以100%保证在他们的list调用中看到我们的对象是第一个出现的。
为了允许删除陈旧/过期的锁定(这些文件应在步骤4的检查中排除,并删除这些文件),这需要为临界区的持续时间设置上限,尽管可以通过创建具有不同UUID的新锁定文件来任意延长锁定时间(当你可以删除旧的锁时,会有一些限制,但是我现在懒得去考虑这个问题).另外,为了确定锁是否过期,不要依赖于本地机器的时间,相反,使用新创建的锁对象的
ModifiedTime
作为校准的时钟源。我并不是说在S3中使用锁文件是个好主意,但这并不能改变它是可能的这一事实。