【问题标题】:A map of atomic counters in DynamoDBDynamoDB 中的原子计数器图
【发布时间】:2016-04-25 22:07:13
【问题描述】:

我有一个 Lambda 函数,它由 dynamoDB(表“A”)触发,并为每个检索到的执行计数和聚合到另一个 dynamoDB 表(表“B”)。 我的用例需要原子计数器的映射,

假设 dynamoDB 表“A”中的一个项目如下所示:

Item 1: {'user': 'foo', 'letter': 'a'}
Item 2: {'user': 'foo', 'letter': 'b'}
Item 3: {'user': 'foo', 'letter': 'b'}
Item 4: {'user': 'foo', 'letter': 'c'}
Item 5: {'user': 'bar', 'letter': 'a'}
Item 6: {'user': 'bar', 'letter': 'd'}

(注意:我的真实用例有数千个“用户”,每个用户有数千个项目,我的“字母”范围约为 400)

因此我希望表“B”看起来像:

Item 1: {'user': 'foo', letter_map {'a' : 1, 'b' : 2, 'c': 1}, total_letters : 4}
Item 2: {'user': 'bar', letter_map {'a': 1, 'd': 1}, total_letters : 2}

我有一个 AWS Lambda 函数,它处理来自表“A”的 dynamoDB 流,并使用以下 UpdateExpression 创建一个 put_item 到表“B”:

UpdateExpression: 'ADD letter_map.#letter :val, total_letters :val',
ExpressionAttributeNames: { '#letter' : RetreivedTableAItem['letter']}
ExpressionAttributeValues: {':val': 1}

问题是表 A 上的 put_items 可以同时发生,我希望原子计数器能帮助我解决并发问题,但我观察到 total_letters 计数器确实是原子的并且性能良好,而 letter_map 映射如果我对同一个用户同时写入,计数器的数量将被重置,

注意:在创建用户时,我创建了一个空的letter_map,以处理提到的here 的限制。 我还尝试将所有可用字母上的整个 letter_map 初始化为 0,但也没有用。

这是正常行为还是错误?

如果正常的话,有什么建议如何实现这个计数器映射任务吗?

【问题讨论】:

  • 你是什么表 A 的哈希/范围键?
  • "如果我对同一个用户同时写入,计数器的 letter_map 映射将被重置" - 你遇到过这种问题吗?
  • 为了简单起见,我把事情缩短了,但我的主分区键相当于“用户”(它实际上是一个散列的userID),我的主排序键是一个letterID。是的,我遇到了这个问题。
  • 所以如果你没有并发写信映射计数器工作?你说的重置是什么意思?字母图计数器再次变为 1?
  • 是的,如果我每次写一个项目并等待它工作。不确定“重置”,但我观察到的是,在将 1000 个项目写入表“A”的两个确切系列之后,表“B”不一样(即不是确定性的)。我认为它“重置”或使用过时的数据。

标签: node.js amazon-web-services amazon-dynamodb aws-lambda


【解决方案1】:

如果您的哈希键是“用户”,则同一用户的表“B”上的 put_item 不能同时发生(通过 lambda)。每个 lambda 可以在一个 dynamo db 分片上工作,并且在每个分片上依次处理项目(以保护排序)。因此,如果“用户”是您的哈希键,则它保证用户“X”将始终位于同一个分片上。

我认为,如果您遇到此类问题(重置),那是因为您的代码中存在其他错误。

来自 aws doc:

发送到您的 AWS Lambda 函数的 Amazon Kinesis 和 DynamoDB Streams 记录按分片严格序列化。这意味着如果您将两条记录放在同一个分片中,Lambda 保证您的 Lambda 函数将在使用第二条记录调用之前成功使用第一条记录调用。如果对一条记录的调用超时、受到限制或遇到任何其他错误,Lambda 将重试直到成功(或记录达到其 24 小时到期),然后再继续下一条记录。不保证不同分片之间记录的顺序,每个分片的处理都是并行进行的。

【讨论】:

  • 谢谢,对于文档的参考,我想问题实际上不是表B上的put_item,而是表A上的原始put_item。不同的记录具有相同的@ 987654324@ 但不同的letterID 可能分布在不同的分片中,因此对于该场景不能保证序列化。虽然不知道如何解决这个问题......
  • '具有相同 userID 但不同 letterID 的不同记录可能分布在不同的分片中' - 如果散列键分布良好,则不会发生这种情况......所以你应该有良好的分布..也许这是你的问题
猜你喜欢
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 2012-05-07
  • 2014-05-02
  • 2014-09-24
  • 2020-08-05
  • 2015-04-22
  • 2010-12-08
相关资源
最近更新 更多