【问题标题】:Amazon S3: How to safely upload multiple files?Amazon S3:如何安全地上传多个文件?
【发布时间】:2018-05-15 15:54:37
【问题描述】:

我有两个使用 S3 来传递信息的客户端程序。该信息是文件列表。

我们称客户端为“上传者”和“下载者”:

上传者做了这样的事情:

  • 上传文件A
  • 上传文件B
  • 上传文件C
  • 上传 SUCCESS 标记文件

下载器做了一些谎言:

  • 检查成功标记
    • 如果找到,请下载 A、B、C。
    • 否则,从其他地方获取数据

这两个程序都在定期运行。上传完成后将填充一个新目录,下载程序将尝试获取可用的最新版本的 A、B、C。

希望意图很明确 — 我不希望下载者看到部分视图,而是获取所有 A、B、C 或跳过该目录。

但是,我认为这行不通。由于最终的一致性,上传者的 PUT 可以重新排序为:

  • 上传文件B
  • 上传 SUCCESS 标记文件
  • 上传文件A
  • ...

此时,下载器可能会运行,看到 SUCCESS 标记,并假设目录已填充(实际上并非如此)。

那么正确的方法是什么?

一个想法是上传者先上传A,B,C,然后反复检查文件是否存储,只有在看到所有文件后,最后写入SUCCESS标记。

这行得通吗?

【问题讨论】:

  • 在 A、B 和 C 上传成功后,能否使用 SQS 从上传程序向下载程序发送 SUCCESS 标记消息(而不是 S3 标记文件)?
  • @AdilB:理想情况下,我希望避免添加更多依赖项。但即使我照你说的做,它有什么帮助?不能保证在收到 SQS 消息后,我现在能够在 S3 中找到所有 A、B、C,是吗?据我了解,这就是“最终一致性”中的全部“最终”。
  • 实际上,再次查看 S3 文档:Amazon S3 provides read-after-write consistency for PUTS of new objects in your S3 bucket in all regions with one caveat. 需要注意的是:只要您不打算在上传文件 A、B 或 C 后覆盖它们,它们应该立即保持一致连同您的 SUCCESS 文件标记到下载程序。
  • @AdilB 几乎是真的。如果您在对象存在之前检查它的存在,那么您在创建该对象时会立即失去一致性......因此成功文件的出现可能会延迟,但只要您不检查任何其他对象,首先,你很好。
  • 是的,我也阅读过这些文档。问题是我的上传器和下载器进程彼此独立运行。我没有办法确保我只在写入标记文件后才读取它,所以我没有办法获得写入后读取的一致性。一旦我进入最终的一致性领域,标记是否不能首先出现,即使它是最后上传的?我不清楚是否有任何关于(最终一致的)标记和 A、B、C 文件外观之间的关系的保证。

标签: amazon-s3 eventual-consistency


【解决方案1】:

在我的项目中偶然发现了类似的问题。 如果目的是保证跨文件一致性(文件 A、B、C 之间)唯一可能的解决方案(纯粹在 s3 中)是:

1) 将它们作为新对象

2) 不要在 put 之前使用 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) 客户端之间可能不一致

【讨论】:

    【解决方案2】:

    可以在 S3 中执行此单个副本。每个文件 (A B C) 都将在其前面添加一个唯一的哈希或版本代码 [e.g. md5sum 由所有三个文件的串联生成。]

    此外,哈希值将被上传到存储桶以及单独的对象中。

    消费文件时,首先读取hash文件并与上一次消费成功的hash进行比较。如果更改,则读取文件并检查每个文件中的哈希值。如果它们都匹配,则数据有效并且可以使用。如果没有,下载的文件应该被丢弃并重新下载(在适当的延迟之后)..

    这将捕获跨多个对象的写入和读取之间偶尔出现的竞争条件。

    这是有效的,因为哈希在所有对象中重复。哈希文件实际上是可选的,作为判断数据是否更新的低成本快速捷径。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-09
      • 2021-06-10
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多