首页 > 解决方案 > 如何在 Cosmos Db 中同步相关集合?

问题描述

我的应用程序需要支持按发票 ID 和客户查找发票。出于这个原因,我创建了两个集合,在其中存储(完全相同)相同的发票文档:

显然你应该在查询时使用分区键,因为有两个查询我需要两个集合。我想未来可能会有更多。

更新主要是对InvoicesById集合进行的,但是我还需要将更改复制到InvoicesByCustomer(和其他)。

是否有任何最佳实践或理智的方法来保持集合同步?

我在想改变提要什么的。我想避免编写此同步代码并避免由于集合之间缺少事务(等)而导致不一致的风险。或者,也许我在这里遗漏了一些重要的东西。

标签: azure-cosmosdb

解决方案


更改提要可以解决问题,尽管我建议在暴力破解问题之前退后一步。


请在此处找到描述拆分问题的详细文章:Azure Cosmos DB。分区。

根据 Microsoft 对可维护数据增长的建议,您应该选择具有最高基数的分区键(在您的情况下,我假设它会是InvoiceId)。主要原因是:

将请求单元 (RU) 消耗和数据存储均匀地分布在所有逻辑分区中。这可确保跨物理分区的 RU 消耗和存储分布均匀。

您不需要使用CustomerId分区键创建单独的容器,因为它不会为您提供所需的,最重要的是,未来可维护的性能,并且当太多发票链接到同一客户时,可能会导致物理分区数据倾斜。

为了获得最佳和可扩展的查询性能,您很可能需要(以及将来InvoiceId的其他人)作为分区键和索引策略。CustomerId

当您查询的数据分布在多个物理分区 (PP) 之间时,消耗中会有轻微的 RU 开销(绝对不是 RU 的倍增,而是每个请求的额外 RU),但与数据时发生的问题相比,它可以忽略不计开始超过 50、100、150GB。


为什么CustomerId可能不是预期增长超过 50GB 的数据集的最佳分区键?

主要原因是 Cosmos DB 旨在水平扩展,并且每个 PP 的预置吞吐量仅限于[total provisioned per container (or DB)] / [number of PP].

一旦由于超过 50GB 大小而发生 PP 拆分,现有 PP 以及两个新创建的 PP 的最大吞吐量将低于拆分前的吞吐量。

因此,想象以下场景(将天数视为操作之间时间的度量):

  1. 您已经创建了具有预置 10k RU 和CustomerId分区键的容器(这将生成一个底层 PP1)。每个 PP 的最大吞吐量为10k/1 = 10k RUs
  2. 逐渐将数据添加到容器中,您最终会得到 3 个大客户的 C1[10GB]、C2[20GB] 和 C3[10GB] 发票
  3. 当另一个客户使用 C4[15GB] 数据加入系统时,Cosmos DB 必须将 PP1 数据拆分为两个新创建的 PP2 (30GB) 和 PP3 (25GB)。每个 PP 的最大吞吐量为10k/2 = 5k RUs
  4. 另外两个客户 C5[10GB] C6[15GB] 被添加到系统中,并且都以 PP2 结束,这导致另一个分裂 -> PP4 (20GB) 和 PP5 (35GB)。现在每个 PP 的最大吞吐量是10k/3 = 3.333k RUs

在此处输入图像描述

重要提示:因此,[Day 2] C1查询的数据最多有 10k RU,但[Day 4]最多只有 3.333k ​​RU,这直接影响查询的执行时间

这是在当前版本的 Cosmos DB (12.03.21) 中设计分区键时要记住的主要事项。



推荐阅读