【问题标题】:How can DynamoDB be HA and eventually consistent at the same time?DynamoDB 怎样才能同时具备 HA 和最终一致性?
【发布时间】:2020-07-08 13:58:18
【问题描述】:
我正在阅读AWS DynamoDB's versioning best practices 并且不理解某些内容:
DynamoDB 如何能够同时实现高可用性和最终一致?!
我对设置的理解是:
- 在您的数据中维护(至少)
version 列
- 插入新记录时,将其作为版本 0 ("v0") 插入
- 每次您想对该记录进行更改时,您都要插入一个新的(递增的)版本,然后将相同的更改也应用到 v0
- 所有读取均针对 v0(最新、最新版本)
但是,当 DynamoDB 作为最终一致的数据库计费时,我不明白它如何强制执行更新条件!有没有人有实施这些指南/实践的经验?
【问题讨论】:
标签:
amazon-web-services
amazon-dynamodb
high-availability
eventual-consistency
【解决方案1】:
DynamoDB 不仅仅是“最终一致”,它实际上还有一个强一致性的概念,described here:
当您请求强一致性读取时,DynamoDB 会返回包含最新数据的响应,反映之前所有成功写入操作的更新。
此外,当更新还涉及读取时 - 由于 UpdateExpresion 或 ConditionExpression - 此读取也始终以高度一致的方式完成。
但不仅如此……仅仅强一致性读取不会帮助您允许对版本进行并发更新。您需要的是使用诸如 乐观锁定 之类的技术来允许新版本的并发写入:
- 读取 (
GetItem) 项目的当前值(在 v0 中)。最终一致没问题。
- 在此项目中,我们找到当前版本号,例如 7。
- 为 v0 写一个新值 (
UpdateItem),版本号为 8(我们读到的 7 之后的一个),使用版本 = 7 的 ConditionExpression。如果此条件失败 (ConditionalCheckFailedException),请转到 1。
- 如果条件成功,则此客户端成功设置版本 8,并且将是唯一成功设置版本 8 的客户端。因此我们发送另一个
UpdateItem 并设置单独的 v8 项.
此技术存在客户端可能在步骤 3 和 4 之间死亡的风险,并且 v8 的条目将丢失,尽管 v0 中的条目将是新的。但是,当您尝试在两个不同的项目中设置相同的数据时,这始终存在风险——一个写入可能成功,另一个将失败——解决此问题的唯一方法是使用transactions 的新 DynamoDB 功能。
【解决方案2】:
虽然其他答案中有一些很棒的信息,但我认为它并不能完全回答您的问题
DynamoDB 如何同时具备 HA 和最终一致性?
答案很简单,DDB 分区是 3 种方式复制...
如果你看过AWS Dynamo Deep Dive video,我强烈推荐。
因此,当您写入 DDB 时,它会将写入传递给所有三个副本,并在三个写入中的两个成功后返回成功给您。
对 DDB 的最终一致性读取也将读取传递给所有三个副本,并在它获得的第一个响应时返回给调用者。
因此,一个写入可能成功到两个副本,但仍然在另一个副本上挂起;并且最终一致的读取会返回过期副本中的数据。
显然,拥有三个副本可为您提供高可用性。
【讨论】:
-
> 因此,当您写入 DDB 时,它会将写入传递给所有三个副本并返回成功三个写入中的任何一个都成功。根据video,这是不正确的。它需要来自存储节点的两次确认。
-