CosmosDB:高效地从大型容器中迁移记录

CosmosDB: Efficiently migrate records from a large container

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

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

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

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

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

根据您更新的评论:

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

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

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

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

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