【问题标题】:AWS Dynamodb scan ordering?AWS Dynamodb 扫描订购?
【发布时间】:2018-11-23 13:06:10
【问题描述】:
我们有一个设置,其中各种工作节点执行计算并更新它们在 DynamoDB 表中的相对状态。该表充当工作节点活动的一种历史记录。看门狗节点需要定期扫描表,并构建一个表示工作节点及其作业的当前状态的对象。因此,我们的应用程序能够扫描表并按时间顺序检索数据(即按时间戳排序)非常重要。该表最终会太大而无法扫描到本地内存以供以后排序,因此我们无法在扫描后对其进行排序。
从AWS documentation读取主键:
DynamoDB 使用分区键值作为内部哈希的输入
功能。哈希函数的输出确定分区
(DynamoDB 内部的物理存储)项目将在其中
存储。具有相同分区键的所有项目存储在一起,在
按排序键值排序。
有关扫描功能的文档似乎没有提及有关返回结果的顺序的任何内容。但是上面引用的最后一部分(我用粗体强调的部分)可以解释为扫描结果是按排序键排序的吗?如果我将所有分区键设置为相同的值,比如“0”,然后使用我的时间戳作为排序键,我可以保证扫描操作将按时间顺序返回数据吗?
一些注意事项:
- 所有代码都是用 Python 编写的,因此我使用 boto3 模块来执行扫描操作。
- 我们的系统架构师坚决反对更新表中的任何条目以反映其当前状态或在作业完成时删除项目的想法。我们只能添加到表中,因此我们每次都需要扫描整个事情以确定工作人员的状态。
- 我正在对扫描操作使用强读取一致性。
【问题讨论】:
标签:
amazon-web-services
amazon-dynamodb
【解决方案1】:
从技术上讲,SCAN 从不保证顺序(尽管作为一个观察,缺乏顺序保证似乎意味着分区是随机排序的,但排序仍然是,嗯,排序。)
您提出的将工作,但是您将在partition-key == 0上执行查询,而不是扫描,然后返回所有项目分区键为0,(最多limit 和可选的向前/向后排序)按排序键排序。
也就是说,这确实不是 dynamo 希望您使用它的方式。例如,它保证您的分区将热运行(因为您已明确将所有内容放在 same 分区上),并且此操作将花费您读取 每个 项目的容量在桌子上。
我建议研究模式,例如使用由 lambda 处理的 dynamodb 流来构建和维护此“当前状态”的物化视图,而不是使用这种昂贵的扫描“轮询”表并导致糟糕的键设计。
【解决方案2】:
最好使用yyyy-mm-dd 作为分区键,而不是全部使用0。每个分区的数据限制为 10 GB,这也意味着每个分区键值的数据不能超过 10 GB。
如果您希望能够检索按日期排序的数据,请采用 ISO 8601 时间戳格式(大致为 yyyy-mm-ddThh-mm-ss.sss),将其拆分为适合您数据的合理位置,并将第一部分用作分区键,第二部分用作分区键部分作为排序键。 (这种方法的另一个优点是您可以对大多数查询使用最终一致的读取,因为可以非常安全地假设在一天(或一小时左右)之后数据被完全复制。)
如果可以管理的话,最好是使用Worker ID或者Job ID作为分区键,然后可以使用全时间戳作为排序键。
正如@thomasmichaelwallace 所提到的,最好使用DynamoDB streams with Lambda 来创建物化视图。
话虽如此,如果您正在处理在工作人员上运行的作业,那么您还应该考虑是否可以通过使用工作流服务而不是数据库来实现您的目标。工作流程将为您维护工作历史和/或当前状态。 AWS 提供Step Functions 和Simple Workflow。