【问题标题】:Dealing with read eventual consistency by retrying GetItem通过重试 GetItem 处理读取的最终一致性
【发布时间】:2020-08-13 16:36:20
【问题描述】:
我构建了一个 API #1,用于在 DynamoDB 中创建一个项目。我正在构建另一个使用 GSI 检索项目的 API #2(输入密钥可能不存在)。但 GSI 读取只能最终保持一致,我不希望 API #1 创建项目但 API #2 没有获取该项目的情况。
所以我在想这个:
- API #1 通过 UpdateItem 创建项目
- API #1 尝试使用 GSI 通过 GetItem 检索项目。不断重试指数退避,直到它得到项目。一旦发生这种情况,最终的一致性就应该结束了。
- API #2 通过 GetItem 使用与上述相同的 GSI 检索项目。由于 API #1 已经获取了该项目,这应该会在第一次尝试时获取该项目。
注意:我不认为 API #2 可以重试 GetItem,因为它的输入键可能永远不存在。
这行得通吗?有没有更好的解决方案?
【问题讨论】:
标签:
amazon-web-services
amazon-dynamodb
eventual-consistency
【解决方案1】:
您正在寻找的属性在文献中被称为 单调读取一致性 - 它是最终一致性(经过足够的时间后,您将始终读取新值),但另外 - 当您读取新值时值一次,进一步读取将不会返回旧值。
我找不到(并且我努力寻找......)任何保证 DynamoDB 最终一致性读取具有单调读取一致性的文档。根据我看到的关于 DynamoDB 实现的演示(我没有任何内部知识),我认为它实际上不具有单调读取一致性:
根据我在这些演示文稿中的理解,DynamoDB 将每条数据保存在三个节点上。三个节点之一是“领导者”(对于这段数据),写入会转到它 - 一致性读取也是如此。但最终一致的读取将随机到达三个节点之一。所以下面的场景是可能的:
- 写入应该更新三个节点上的 GSI 的三个副本 - X、Y 和 Z - 但此时仅更新 X 和 Y,Z 尚未更新。
- API 1 从 GSI 中读取数据并随机询问节点 X 并获取新值。
- 现在 API 2 从 GSI 读取。它随机获取节点Z,并获取旧值!
所以有可能在你的应用程序找到新值之后,另一个读取将找不到它:-(
如果其他人可以找到更好的文档来解决这个问题,而不仅仅是我的“我从演示文稿中理解的内容”,我也很乐意阅读他们的答案。