【问题标题】:Is DynamoDB guaranteed to converge to latest data when updates happen fast?DynamoDB 是否保证在快速更新时收敛到最新数据?
【发布时间】:2020-12-15 23:57:17
【问题描述】:

很明显,Dynamo 在并行运行更新/删除时不是线程安全的(除非使用乐观更新锁定或条件写入)。

我想知道的是,在一个接一个地运行更新而没有任何顺序暂停时是否存在一致性问题的风险,像这样(Javascript):

await dynamo
  .put({ // PUT creates a record if it doesn't exist
    TableName: "table-name",
    Item: {
      id,
      value: "some value"
    }
  })
  .promise();
await dynamo
  .delete({
    TableName: "table-name",
    Key: {
      id
    }
  })
  .promise();

// wait for X seconds for eventual consistency here
const result = await dynamo
  .get({
    TableName: "table-name",
    Key: {
      id
    }
  })
  .promise();
if (result.Item) {
  throw new Error('Oh no, record should have been deleted!');
}

我已经运行了这段代码 1000 次,结果表明在这种情况下可以依赖 Dynamo 来按预期运行(最后更新/删除获胜),但我想确定(文档的链接?)。

更新:换句话说,我想知道当更新发生得很快时,Dynamo 是否保证遵守我发送更新的顺序。

【问题讨论】:

  • 这很有帮助,似乎表明我的预期是正确的,引用:“如果您在短时间内重复读取请求,则响应应该返回最新数据”。但是,它并没有具体提到一个接一个地快速发生的更新。我在想——也许 Dynamo 在执行 DELETE 之前需要在内部读取?如果它在数据库还没有变得一致的时候读取,它可能会“认为”没有什么可以删除?
  • 维基百科对“最终一致性”的定义也不给我乐观:“最终一致性是分布式计算中用于实现高可用性的一致性模型,它非正式地保证,如果没有新的更新给定的数据项,最终对该项的所有访问都将返回最后更新的值”。请注意定义中的“无新更新”部分

标签: database amazon-dynamodb eventual-consistency


【解决方案1】:

如果您想保证您将读取数据的最新版本,则应使用强一致性读取。这样,当您查询时,您一定会读取到最新的值。

如果您使用最终一致性,您可能不会读取最新值(大约 33% 的机会读取过时)。根据经验,读取将过时的时间段约为毫秒,并且自上次写入通过以来的时间越长,过时读取的结果趋于零,但没有具体的 SLA 可以持续多长时间进行最终一致的读取以达成共识。根据经验,任何超过几秒钟的内容都可以,但同样,如果您需要强保证,则必须使用强一致性读取。

【讨论】:

  • 这并不能真正回答我的问题。也许我的问题不清楚。我在“更新”部分对我的问题进行了不同的表述
【解决方案2】:

得到了 AWS 支持的回复:

简而言之,是的。无论更新发生得有多快,最新的更新都会“获胜”。您不会遇到 DynamoDB 服务认为数据一致但不一致的情况,从而导致长期陈旧状态。对 DynamoDB(PutItem、UpdateItem、DeleteItem)的所有“写入”类型命令(返回 HTTP 200 成功代码)均按顺序处理。

如果我正确理解了您在 StackOverflow 上的示例,则您正在放置一个项目,然后立即将其删除。以该顺序运行时,该项目将始终被删除。永远不会出现 PutItem 在 DeleteItem 之前发生得太近的情况,然后您最终会得到未按预期删除的项目。只有在读取数据时才需要关注最终一致性与强一致性 [1]。


您可能知道,从 DynamoDB 表中读取项目有两种不同的方式,最终一致(默认)和强一致。

[+] 最终一致的读取是一半的成本(例如 0.5 RCU 用于 4 KB 项目)但如果该项目在读取前几秒钟内更新,则可能会返回陈旧数据。 [+] 强一致性读取是完全成本的(例如 1 个 RCU 用于 4 KB 项目),可能会导致稍高的网络延迟,并会导致以下结果:

  1. HTTP 200 - 如果项目存在则返回该项目,如果不存在则返回 null。无论 LAST Put/Update/Delete 在读取之前多久运行一次,都是如此。
  2. HTTP 500 - 我们端发生内部网络错误,您需要再次尝试读取(这种情况很少见) 您不会看到返回的是过时的数据或最近删除的项目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 2015-01-09
    • 2018-02-01
    • 1970-01-01
    相关资源
    最近更新 更多