DynamoDB 架构设计
DynamoDB Schema Design
我正在考虑将 Amazon AWS DynamoDB 用于我正在进行的项目。这是情况的要点:
我将为数百台机器收集大量能源使用数据(大约每 5 分钟读取一次能源读数)。每台机器都在一个区域中,每个区域都在一个网络中。
然后我将按区域和网络、按小时和按天汇总这些单独的读数。
我的想法是,通过这样做,我将能够在 network_day
table 上针对 DynamoDB 执行一个查询,并且 return 任何一天的能源使用情况很快。
这是我此时的架构:
table_name | hash_key | range_key | attributes
______________________________________________________
machine_reading | machine.id | epoch | energy_use
machine_hour | machine.id | epoch_hour | energy_use
machine_day | machine.id | epoch_day | energy_use
zone_hour | machine.id | epoch_hour | energy_use
zone_day | machine.id | epoch_day | energy_use
network_hour | machine.id | epoch_hour | energy_use
network_day | machine.id | epoch_day | energy_use
当我 运行 汇总 cronjob 时,我并没有立即在测试中看到如此出色的性能,所以我只是想知道是否有更多经验的人可以对我的关键设计发表评论?到目前为止,我唯一的经验是使用 RDS,但我非常想了解 DynamoDB。
编辑:
我用于汇总的 cronjob 的基本结构:
foreach network
foreach zone
foreach machine
add_unprocessed_readings_to_dynamo()
roll_up_fixture_hours_to_dynamo()
roll_up_fixture_days_to_dynamo()
end
roll_up_zone_hours_to_dynamo()
roll_up_zone_days_to_dynamo()
end
roll_up_network_hours_to_dynamo()
roll_up_network_days_to_dynamo()
end
我在 Dynamo 中使用上一个函数的值进行下一次汇总,即
- 我使用区域小时来累积区域天数
- 然后我用zone days来汇总
网络天数
这就是(我认为)造成了很多不必要的 reads/writes。现在我可以处理低吞吐量,因为我的样本量只有 100 个读数。当它扩展到预期包含大约 9,000,000 个读数时,我的担忧就开始了。
您使用的 table 的预配置吞吐量是多少?你是如何进行汇总的?您正在阅读所有内容并过滤/过滤范围键等吗?
在这种情况下你需要滚动 up/a cron 作业吗?
为什么不使用 table 作为读数
machine_reading | machine.id | epoch_timestamp | energy_use
和 table 用于聚合
hash_key 可以是聚合类型,范围键可以是聚合名称
例子:
区域,区域 1
区域,区域 3
1940 年 3 月 29 日
获取机器数据时,将其转储到第一个 table 中,然后使用原子计数器在第二个 table 中增加实体:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.AtomicCounters
首先,DynamoDB 中的时间序列数据很难正确处理,但并非不可能。
DynamoDB 使用散列键对数据进行分片,因此使用 machine.id 意味着你们中的一些人将拥有热键。然而,这实际上是数据量和您期望的 IOPS 的函数。在您超过 1000 个读取或写入 IOPS 之前,DynamoDB 不会创建第二个分片。如果您希望远低于该水平,您可能没问题,但如果您希望扩展到该水平以上,那么您可能需要重新设计,特别是在您的哈希键中包含一个日期组件来分解。
关于性能,您是否达到了配置的读取或写入吞吐量水平?如果是这样,将它们提升到某个疯狂的高水平并重新 运行 测试,直到瓶颈成为您的代码。这可能很简单,只要适当地设置吞吐量级别即可。
但是,对于您的实际代码,在没有看到您正在执行的实际 DynamoDB 查询的情况下,一个可能的问题是读取了太多数据。确保您没有从 DynamoDB 读取超出您需要的数据。由于您的范围键是日期字段,因此使用范围条件(而不是过滤器)来减少您需要读取的记录数。
确保您的代码使用多线程执行汇总。如果您无法使 DynamoDB 预置容量饱和,问题可能不是 DynamoDB,它可能是您的代码。通过使用多个线程并行执行汇总,您应该能够看到一些性能提升。
我正在考虑将 Amazon AWS DynamoDB 用于我正在进行的项目。这是情况的要点:
我将为数百台机器收集大量能源使用数据(大约每 5 分钟读取一次能源读数)。每台机器都在一个区域中,每个区域都在一个网络中。
然后我将按区域和网络、按小时和按天汇总这些单独的读数。
我的想法是,通过这样做,我将能够在 network_day
table 上针对 DynamoDB 执行一个查询,并且 return 任何一天的能源使用情况很快。
这是我此时的架构:
table_name | hash_key | range_key | attributes
______________________________________________________
machine_reading | machine.id | epoch | energy_use
machine_hour | machine.id | epoch_hour | energy_use
machine_day | machine.id | epoch_day | energy_use
zone_hour | machine.id | epoch_hour | energy_use
zone_day | machine.id | epoch_day | energy_use
network_hour | machine.id | epoch_hour | energy_use
network_day | machine.id | epoch_day | energy_use
当我 运行 汇总 cronjob 时,我并没有立即在测试中看到如此出色的性能,所以我只是想知道是否有更多经验的人可以对我的关键设计发表评论?到目前为止,我唯一的经验是使用 RDS,但我非常想了解 DynamoDB。
编辑:
我用于汇总的 cronjob 的基本结构:
foreach network
foreach zone
foreach machine
add_unprocessed_readings_to_dynamo()
roll_up_fixture_hours_to_dynamo()
roll_up_fixture_days_to_dynamo()
end
roll_up_zone_hours_to_dynamo()
roll_up_zone_days_to_dynamo()
end
roll_up_network_hours_to_dynamo()
roll_up_network_days_to_dynamo()
end
我在 Dynamo 中使用上一个函数的值进行下一次汇总,即
- 我使用区域小时来累积区域天数
- 然后我用zone days来汇总 网络天数
这就是(我认为)造成了很多不必要的 reads/writes。现在我可以处理低吞吐量,因为我的样本量只有 100 个读数。当它扩展到预期包含大约 9,000,000 个读数时,我的担忧就开始了。
您使用的 table 的预配置吞吐量是多少?你是如何进行汇总的?您正在阅读所有内容并过滤/过滤范围键等吗?
在这种情况下你需要滚动 up/a cron 作业吗?
为什么不使用 table 作为读数 machine_reading | machine.id | epoch_timestamp | energy_use
和 table 用于聚合 hash_key 可以是聚合类型,范围键可以是聚合名称 例子: 区域,区域 1 区域,区域 3 1940 年 3 月 29 日
获取机器数据时,将其转储到第一个 table 中,然后使用原子计数器在第二个 table 中增加实体: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.AtomicCounters
首先,DynamoDB 中的时间序列数据很难正确处理,但并非不可能。
DynamoDB 使用散列键对数据进行分片,因此使用 machine.id 意味着你们中的一些人将拥有热键。然而,这实际上是数据量和您期望的 IOPS 的函数。在您超过 1000 个读取或写入 IOPS 之前,DynamoDB 不会创建第二个分片。如果您希望远低于该水平,您可能没问题,但如果您希望扩展到该水平以上,那么您可能需要重新设计,特别是在您的哈希键中包含一个日期组件来分解。
关于性能,您是否达到了配置的读取或写入吞吐量水平?如果是这样,将它们提升到某个疯狂的高水平并重新 运行 测试,直到瓶颈成为您的代码。这可能很简单,只要适当地设置吞吐量级别即可。
但是,对于您的实际代码,在没有看到您正在执行的实际 DynamoDB 查询的情况下,一个可能的问题是读取了太多数据。确保您没有从 DynamoDB 读取超出您需要的数据。由于您的范围键是日期字段,因此使用范围条件(而不是过滤器)来减少您需要读取的记录数。
确保您的代码使用多线程执行汇总。如果您无法使 DynamoDB 预置容量饱和,问题可能不是 DynamoDB,它可能是您的代码。通过使用多个线程并行执行汇总,您应该能够看到一些性能提升。