【问题标题】:CosmosDB: Efficiently migrate records from a large containerCosmosDB:高效地从大型容器迁移记录
【发布时间】:2020-07-17 04:23:04
【问题描述】:

我在CosmosDB 中创建了一个容器,用于跟踪有关每个 API 调用的元数据(时间戳、用户 ID、方法名称、持续时间等)。分区键设置为UserId,每个id都是随机的Guid。这个容器还可以帮助我对每个用户实施速率限制。到目前为止,一切都很好。现在,我想通过将记录移动到Azure Table(或其他东西)来定期清理这个容器,以便长期存储并生成报告。迁移记录还可以帮助我避免 20GB 的逻辑分区大小限制。

但是,我担心跨分区查询最终是否会咬我。比如说,我想迁移一周前创建的所有记录。另外,假设我有数百万活跃用户。因此,这个容器看到了很多活动,我无法在查询中指定分区键。我正在阅读,当 RU/s 和存储大小都很大时,我们应该避免跨分区查询。见this。我不知道将来要处理多少物理分区。

我的设计完全不成立吗?如何有效地迁移记录?我希望 CosmosDB 团队能够看到这一点并帮助我找到解决此问题的方法。

【问题讨论】:

  • 4c74356b41 的建议很好。随着时间的推移,表存储对于大量数据来说非常便宜——比 CosmosDb 便宜得多。所以我的问题是,如果你想最终将 API 调用历史存储在 Table 存储中,为什么首先要写入 CosmosDB?您是否有理由不直接写入表存储并完全跳过 CosmosDb?
  • Rob,我目前对表存储没有太多经验。在 Cosmos v3 中,我使用 WhereCount 方法编写 LINQ 查询,以对特定 API 路由和 userId 组合实施速率限制。表存储是否支持这种类型的 LINQ 功能?就像您的建议一样,如果可以的话,我很想使用表格存储。我通过 CosmosDB 获得了 IOrderedQueryable<T>。我不想获取内存中的所有 Table 行进行过滤和计数。
  • 啊,所以您要在每个 API 调用上查询 CosmosDb 以了解用户在限制窗口中执行了多少次查询?如果查询率超过阈值,您会拒绝 API 请求并返回类似 HTTP 429 的内容?
  • 没错!该功能是很久以前实现的。当然,现在我需要迁移陈旧的数据。

标签: azure nosql azure-cosmosdb azure-table-storage


【解决方案1】:

更简单的方法是使用 time to live 并同时将 events\data 写入 cosmos db 和表存储,以便它永远保留在表存储中,但在 TTL 到期时从 Cosmos DB 中消失.您可以在文档级别指定 TTL,因此如果您需要一些文档的寿命更长 - 可以这样做。

另一种方法可能是使用change feed

【讨论】:

    【解决方案2】:

    根据您更新的 cmets:

    • 您正在为每个 API 请求编写 CosmosDb 文档。
    • 进行 API 调用时,您将在 CosmosDB 中查询给定时间段内的所有 API 调用,分区为 userId。如果文档数超过阈值,则返回 HTTP 429 等错误。
    • 您希望存储 API 调用信息以进行长期分析。

    如果您的 API 得到大量用户的大量使用,那么从存储和处理的角度来看,使用 CosmosDB 进行扩展的成本将会很高。

    对于速率限制,请考虑使用 Redis 缓存的this rate limiting patternThe StackExchange.Redis package 很成熟,有很多指导和代码示例。对于您的问题,这将是一个重量更轻且可扩展的解决方案。

    因此,对于每个 API 调用,您将:

    1. 为拨打电话的用户读取 Redis 密钥。检查它是否超过您的阈值。
    2. 增加用户的 Redis 密钥。
    3. 将 API 调用写入 Azure 表存储,分区键可能是 userId,行键是对您有意义的任何内容。

    【讨论】:

    • 在 CosmosDB 中实现速率限制时,我考虑过 Redis。我什至记得问过 CosmosDB 团队成员,Redis 在 CosmosDB 之上是否过于矫枉过正。答案是肯定的。请参阅:medium.com/@marcodesanctis2/… 理想情况下,我想避免使用另一层/故障点使后端设计复杂化。同时,成本可能是最大的痛点。谢谢你。我会考虑这个选项。
    • 如果您确实使用 CosmosDb 来限制 API 的速率,我赞同 4c74356b41 的建议,即使用 Azure 函数来监控 CosmosDB 更改源。对于每一个变化,你可以查看它是否是一个 API 调用,然后将 API 调用写入 Table Storage。
    • 这是一个重要的选择。我倾向于 Redis 方法,考虑到在我的情况下,CosmosDB 将为每个 API 调用收取 3 个额外的 RU/s(一个用于读取当前计数,一个用于编写文档,一个用于 TTL)。是否有任何用于 Redis 速率限制的 C# 示例?我找不到任何东西。
    • 不幸的是,我没有想到任何例子。
    • 我将 API 跟踪移至表存储并实现了 Redis 缓存层。一切正常。谢谢你的指导!我选择了另一个答案作为接受的答案,因为它更适合这个问题,但我最终还是按照你的方向走。
    猜你喜欢
    • 2011-09-10
    • 2022-06-15
    • 2021-12-06
    • 1970-01-01
    • 2016-03-01
    • 1970-01-01
    • 2021-12-07
    • 2015-09-26
    • 1970-01-01
    相关资源
    最近更新 更多