amazon-web-services - DynamoDB 是否适合我需要访问记录和摘要(聚合)信息的每天 100 万事件的场景

标签 amazon-web-services amazon-dynamodb data-modeling aws-iot

来自 C 世界的软件工程师闯入云空间。我试图了解我是否可以将 DynamoDB 用于我的所有场景需求,如果我根本不应该使用它,或者我是否应该将 DynamoDB 用于某些场景然后卸载到另一个数据库(可能是更传统的 RDMS)以用于其他场景。
我有一堆机器向我的 AWS API 发送遥测数据。我目前的想法是将这些事件放在 DynamoDB 表中。在第一年,我预计每天表中总共会有大约 100 万个新条目(平均 > 10 个每秒),峰值时间接近每秒 100 个事件。遥测事件的大小将为 0.5-1KB。首先,我只想捕获每个遥测数据并记录下来。这大约是每天 1GB。
我会使用 RDMS,但我担心 ACID 属性,随着数据库大小的增长,我们每秒有 10 到 100 次写入,数据库访问将显着减慢。 我的担心是否正确 ,或者传统的 RDMS 是否适合我的需求?我不觉得我需要 RDMS 的原子保证(我可以接受最终的一致性),尤其是对于读取/聚合查询。
我在想我的主键是机器 ID(分区)和时间 unix 毫秒纪元(排序键)之间的复合键。这应该支持关键场景场景,例如检索特定时间范围和一组机器的所有遥测事件列表。
但是,我还希望做其他事情,例如能够获取各种遥测事件的每日总数,例如触发机器传感器的次数(即计数)。或者列出一组机器的温度高于某个值时记录的所有遥测事件。遥测事件是异构的 - 有许多类型,例如温度、触发等,我需要能够针对给定的一组机器 ID 和时间窗口快速过滤特定类型的遥测事件。
所以你可以想象我的一个查询可能看起来像“对于这个时间窗口和这组机器,列出记录了超过 70 度的温度的所有温度(类型)遥测事件”。前 2 个约束来自我的分区 (machineId) 和排序键 (time),但后一个将查询温度和值大于 70 的所有遥测类型。这是我约束的 4 个字段。我是否应该接受可以查询 machineId 和 time 的现实,但必须从该查询返回的结果中扫描遥测类型和值?
此外,这个 dynamodb 表摄取遥测数据,但前端需要提供诸如上次接收遥测事件、上次机器服务时间、特定遥测事件的每日计数等内容的摘要信息。我不想每次在前端重新加载摘要页面时都重新查询它们。是否应该在遥测到达时计算这些聚合,然后将其存储在单独的表中(或者,如果性能需要,可以在内存中类似于 redis)。这在技术上是流处理吗?
我在网上读到好的设计通常只使用一张 table (单 table 设计),但我发现很难理解如何到达那里。在我希望能够查看单个遥测事件但也可以快速访问聚合信息的场景中,这可能没有意义。
写出这个问题后,这是我的直觉现在告诉我的:

  • 使用 dynamodb
  • 在您摄取遥测事件时,为最常见的用户场景(每小时、每天、每周、每月总计)创建聚合并将它们存储在某处以便快速访问。在此处调查流处理和/或运动。
  • 对于需要聚合的不太常见的用户场景,请使用另一种技术,如 Redshift、Athena

  • 谢谢,
    托马斯

    最佳答案

    My current idea is to put these events in a DynamoDB table. In the first year I am expecting about 1M new entries total in the table per day (average > 10 per second), with peak times being closer to 100 events per second. The size of the telemetry events will be 0.5-1KB.


    听起来像是 DynamoDB 的一个非常好的用例——每秒大量相对较小的写入。

    I would use RDMS, but I am concerned that with the ACID properties, as the database size grows given we have 10s to 100s writes per second, database access will slow down significantly. Am I right to be concerned, or will a traditional RDMS be suitable for my needs?


    RDBMS 可以扩展以处理这种负载,是的。不是微不足道的,但也不是这个世界上的事。
    既然您提到了 DynamoDB,我假设您对 AWS 中的其他服务没问题 — 我建议您查看 Aurora 以了解此类情况,如果
    您决定使用 RDBMS。
    但这听起来很浪费,尤其是因为:

    I don't feel I need the atomic guarantees of an RDMS (I can live with eventual consistency) especially for reading/aggregating queries.


    所以,它指向的不是 RDBMS。不过,不一定是 DynamoDB。
    但是,您需要小心使用数据模型。
    现在...

    Should I accept the reality that [...] will have to scan for the telemetry type and value from the results return in that query?


    几乎可以肯定不是。设计基于 DynamoDB 的数据模型,从一开始就要求您扫描越来越多的数据,这是一个糟糕的主意。如果你那样做,你将来会因此而讨厌自己。
    这里要记住的非常重要的一点是,您不希望由于规模的增加而使操作花费更长的时间(例如,就像您对 RDBMS 的担忧一样)。
    表越大,扫描操作所需的时间就越长。因此,随着您在表中积累越来越多的数据,您的系统性能会随着时间的推移而降低。例如,您可以通过将“非热”数据从“主”表卸载到“归档”表来解决此问题。但这增加了管理整个系统的复杂性。
    相反,尝试设计您的数据模型,以便无论您拥有的数据总量如何,操作都能保持其性能。例如,确保您的查询始终仅限于对一个(或至少为 O(1))项目集合(即具有相同分区键的项目)上的操作。

    the frontend needs to present summary information [...]. I don't want to have to re-query them every time [...]. Should these aggregates be calculated when the telemetry arrives and then stored in a separate table (or perhaps if performance needs it, in memory something like redis). Is this technically stream processing?


    流处理在这里是一个很好的方法。
    避免每次显示前端时都重新计算此摘要信息是绝对正确的。将其“即时”聚合并将其存储在某处是一种非常好的方法。然后前端只需“显示最新的预先计算的数据”:微不足道。
    现在,问题变成了何时聚合、存储在哪里以及如果聚合失败该怎么办。
  • 何时聚合。

  • 您可以在遥测到达时执行此操作,是的,但是如果您要将其写入 DynamoDB,请记住您可以使用 DynamoDB Streams — 每个新项目都会写入可以重播的持久流中(以防万一您需要重新计算某些内容)并且您可以让它自动调用 Lambda 函数,例如,执行您的聚合。
  • 存放的地方。

  • 存储在内存中的风险是增加丢失摘要的机会,并且不得不重新计算它。我更喜欢这里至少有一些耐用性。最好的解决方案取决于很多因素,包括你如何为这个前端提供服务(静态 html?不可缓存的 API 请求?),以及你希望它多久更新一次(每 X 秒?每一个新的部分遥测数据?)。
    您可能想在这里研究的一件事是 Kinesis Data Analytics:它可以为您自动运行所有聚合,并将结果写入您选择的一些持久存储。然后,您可以决定该摘要如何进入前端(例如,每次从它请求,将其写入诸如 Redis 之类的东西,反转控制并将其推送到为前端提供服务的服务器,以便他们不必发出请求等) .
  • 如果这失败了怎么办。

  • 这部分非常重要。如果摘要由于处理管道中的故障而过时,或者在内存缓存服务器丢失或持久存储不可用的情况下丢失数据,您不希望前端中断。因此,确保您清楚地了解如何处理这些情况非常重要。
    您应该在这里考虑的另一个方面是如果您丢失当前的聚合该怎么办。 DynamoDB 包含所有测量值,因此您应该能够重新计算所有摘要。但请记住——数据在增长,这将需要扫描,因此从头开始重新计算可能需要很长时间。
    您可能想要编写“检查点”(例如,“直到第 X 天的所有汇总数据”)或更粗略的预聚合(例如,“仅针对第 X 天的所有汇总数据”)假设您正在计算的统计数据可以正确地从预聚合(例如,您可以使用“平均值”或“最大值”来实现;您不能使用 p99 来实现)。将这些检查点保存到 S3 可能是一个好主意。或者,使用我在别处提到的多个 DynamoDB 表可能很有用(添加到的“热”表和将存档数据移动到的“非热”表,并且您始终维护此存档表的摘要某处;这样,您只需扫描一小部分“热”数据)。

    I read online that good design typically only uses one table (single table design), but I am finding it hard to understand how to get there.


    是的……小心点。虽然我不认为它本质上是一个糟糕的设计,但事实是很多人荒谬地过度宣传它。主要问题是改进设计非常困难。
    话虽如此,请记住这不是 RDBMS。我这样说是因为我觉得那是你更习惯的事情。但是在 DynamoDB 中设计数据模型是非常不同的(单表与否)。重复数据是它的正常部分,“正常形式”是不可取的。
    要始终牢记的主要事情是,您希望读取和写入操作对于数据量都是 O(1),同时您希望能够灵活地查询所需的所有信息。单表不是自动为您提供的东西,也不一定简化实现它。

    After writing out this question, here is what my intuition is telling me right now: [...]


    我会说你有很好的直觉。发现。
    关于第 3 点,Athena 和 Redshift,请记住,它们通常更适合“批处理”(尽管不是唯一的)。换句话说,你不希望你的前端,例如,永远向任何一个发送查询并等待结果。您可能需要一个进程来查询它们中的任何一个并将预先计算的结果存储在例如 S3 上,然后将显示在您的前端之类的东西上。但是它们应该与低延迟请求分开。

    关于amazon-web-services - DynamoDB 是否适合我需要访问记录和摘要(聚合)信息的每天 100 万事件的场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65586045/

    相关文章:

    数据库约束——保留还是忽略?

    amazon-web-services - 从 AWS EC2 实例下载文件到本地主机

    python - 在 Jenkins 中构建 Docker 镜像时如何传递 AWS 凭证?

    python - 我正在使用 Flask,并且想要将一个项目插入到 DynamoDB 表中,endpoint_url 应该是什么?

    Cassandra:列出用户最近的对话

    active-directory - 大多数 LDAP 管理员是否手动创建 LDIF?

    amazon-web-services - 使用AWS CodeBuild的语义版本控制

    amazon-web-services - AWS OpsWorks : use Redis instead of Memcached

    node.js - Node JS 嵌套函数被跳过

    java - 尝试为 DynamoDB 初始化客户端时 Amazon Lambda 超时