我有两个客户端程序正在使用S3来传递一些信息。该信息是文件列表。
让我们称客户为“上传者”和“下载者”:
上传程序执行以下操作:
下载程序可以解决这个问题:
这两个程序都在定期运行。上传程序将在完成后填充新目录,下载程序将尝试获取最新版本的A,B,C。
希望意图明确 - 我不希望下载者看到部分视图,而是获取所有A,B,C或跳过该目录。
然而,我认为这不符合要求。由于最终的一致性,上传者的PUT可以重新排序为:
此时,下载程序可能会运行,请参阅SUCCESS标记,并假设该目录已填充(不是)。
那么什么是正确的方法,在这里?
一个想法是上传者首先上传A,B,C,然后反复检查文件是否存储,并且只有在看到所有文件之后,才最后写入SUCCESS标记。
那会有用吗?
答案 0 :(得分:0)
在我的项目中偶然发现类似问题。 如果要保证跨文件的一致性(在文件A,B,C之间),则唯一可行的解决方案(仅在s3内)是:
1)将它们作为新对象
2)不要在放置之前使用HEAD或GET请求明确检查是否存在。
要完全一致地执行写入后读取行为(https://aws.amazon.com/about-aws/whats-new/2015/08/amazon-s3-introduces-new-usability-enhancements/),需要上述两个约束条件
每次更新文件时,都需要生成一个唯一的前缀(文件夹)名称,然后将此名称放入要更新的标记文件(清单)中。
清单将具有稳定的名称,但最终将保持一致。一些客户端可能会获得旧版本,而某些可能会获得新版本。 旧清单将指向旧“文件夹”,而新清单将指向新“文件夹”。这样,每个客户端将仅读取旧文件或仅读取新文件,但从不读取,因此可以实现跨文件的一致性。仍然不同的客户端可能最终具有不同的版本。如果客户不断拉动清单并及时更新更改,他们最终也将变得一致。
客户端不一致的可能解决方案是将清单元数据从s3移到一致的数据库(例如dynamo db)中
使用纯s3方法的一些明显警告:
1)要求每次都上传完整的文件集(无法进行增量更新)
2)最终需要清除旧的过时文件夹
3)客户需要不断提取清单以进行更新
4)客户端之间可能会不一致
答案 1 :(得分:0)
可以在 S3 中执行此单份副本。每个文件(A B C)都将预先添加一个唯一的哈希或版本代码[例如md5sum 由所有三个文件的串联生成。]
此外,哈希值也将上传到存储桶以及一个单独的对象中。
在消费文件时,首先读取哈希文件并与上次成功消费的哈希进行比较。如果更改,则读取文件并检查每个文件中的哈希值。如果它们都匹配,则数据有效并可使用。如果没有,则应丢弃已下载的文件并再次下载(适当延迟后)。
这将捕获跨多个对象的写入和读取之间的偶然竞争条件。
这是有效的,因为散列在所有对象中都是重复的。哈希文件实际上是可选的,作为判断数据是否更新的低成本快速捷径。