你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

跨分区重新分发吞吐量(预览版)

适用对象: NoSQL MongoDB

默认情况下,Azure Cosmos DB 在所有物理分区中平均分发数据库或容器的预配吞吐量。 但由于工作负载的倾斜或分区键的选择,某些逻辑(以及物理)分区可能会比其他分区需要更多的吞吐量。 对于这些场景,Azure Cosmos DB 能够跨物理分区重新分发预配的吞吐量。 跨分区重新分发吞吐量有助于实现更好的性能,且无需根据最热分区配置总体吞吐量。

吞吐量重新分发功能适用于使用预配吞吐量(手动和自动缩放)的数据库和容器,不适用于无服务器容器。 你可以使用 Azure Cosmos DB PowerShell 或 Azure CLI 命令更改每个物理分区的吞吐量。

何时使用此功能

一般情况下,建议在满足下列两个条件的情况下使用此功能:

  • 始终显示 429 个响应的总体比率超过 1-5%
  • 你拥有一致的、可预测的热分区

如果未显示 429 个响应且端到端延迟是可接受的,则无需为每个分区重新配置 RU/s。 如果工作负载具有连续的流量,且所有分区偶尔出现不可预测的峰值,则建议使用自动缩放突发容量(预览版)。 自动缩放和突发容量将确保能够符合吞吐量要求。 如果每个分区的 RU/秒数量较少,你还可以使用分区合并(预览版)来减少分区数量并确保每个分区更多 RU/秒以获得相同的总预配吞吐量。

示例方案

假设我们使用一个工作负载来跟踪零售店中发生的交易。 由于大部分查询都是按 StoreId 进行划分,因此我们按 StoreId 进行分区。 然而,随着时间的推移,我们发现某些商店的活动比其他商店的活动更多,因此需要更多的吞吐量来为其工作负载提供支持。 我们正在查看针对这些 StoreId 的请求的速率限制 (429),429 个响应的总体比率大于 1-5%。 同时,其他商店不太活跃,所需吞吐量也较少。 接下来介绍如何重新分发吞吐量以实现更好的性能。

第 1 步:确定哪些物理分区需要更多的吞吐量

可通过两种方法来确定是否存在热分区。

选项 1:使用 Azure Monitor 指标

若要验证是否存在热分区,请导航到“见解”>“吞吐量”>“按 PartitionKeyRangeID 列出的规范化 RU 消耗量(%)”。 筛选到特定数据库和容器。

每个分区键范围 ID 映射到一个物理分区。 寻找一个规范化 RU 消耗量始终高于其他 PartitionKeyRangeId 的 PartitionKeyRangeId。 例如,一个值始终为 100%,但其他值为 30% 或更低。 诸如此类的模式可以指示热分区。

Screenshot of Normalized RU Consumption by PartitionKeyRangeId chart with a hot partition.

选项 2:使用诊断日志

可以根据诊断日志中 CDBPartitionKeyRUConsumption 的信息来获取有关在第二级粒度上消耗最多 RU/s 的逻辑分区键(和相应的物理分区)的更多信息。 请注意,示例查询使用 24 小时仅实现说明目的 - 建议通过至少 7 天的历史记录来了解该模式。

查找一段时间内消耗最多 RU/s 的物理分区 (PartitionKeyRangeId)

CDBPartitionKeyRUConsumption 
| where TimeGenerated >= ago(24hr)
| where DatabaseName == "MyDB" and CollectionName == "MyCollection" // Replace with database and collection name
| where isnotempty(PartitionKey) and isnotempty(PartitionKeyRangeId)
| summarize sum(RequestCharge) by bin(TimeGenerated, 1s), PartitionKeyRangeId
| render timechart

对于给定的物理分区,查找每小时消耗最多 RU/s 的前 10 个逻辑分区键

CDBPartitionKeyRUConsumption 
| where TimeGenerated >= ago(24hour)
| where DatabaseName == "MyDB" and CollectionName == "MyCollection" // Replace with database and collection name
| where isnotempty(PartitionKey) and isnotempty(PartitionKeyRangeId)
| where PartitionKeyRangeId == 0 // Replace with PartitionKeyRangeId 
| summarize sum(RequestCharge) by bin(TimeGenerated, 1hour), PartitionKey
| order by sum_RequestCharge desc | take 10

步骤 2:确定每个物理分区的目标 RU/s

确定每个物理分区的当前 RU/s

首先,确定每个物理分区的当前 RU/s。 你可以使用 Azure Monitor 指标 PhysicalPartitionThroughput 并按维度 PhysicalPartitionId 进行拆分,以查看每个物理分区的 RU/s 值

另外,如果之前没有更改过每个分区的吞吐量,可以使用以下公式:Current RU/s per partition = Total RU/s / Number of physical partitions

请按照缩放预配吞吐量 (RU/s) 的最佳做法一文中的指导来确定物理分区数。

还可以使用 PowerShell Get-AzCosmosDBSqlContainerPerPartitionThroughputGet-AzCosmosDBMongoDBCollectionPerPartitionThroughput 命令读取每个物理分区上的当前 RU/s。

使用 Install-Module 安装启用了预发行功能的 Az.CosmosDB 模块。

$parameters = @{
    Name = "Az.CosmosDB"
    AllowPrerelease = $true
    Force = $true
}
Install-Module @parameters

使用 Get-AzCosmosDBSqlContainerPerPartitionThroughputGet-AzCosmosDBSqlDatabasePerPartitionThroughput 命令读取每个物理分区上的当前 RU/s。


// Container with dedicated RU/s
$somePartitionsDedicatedRUContainer = Get-AzCosmosDBSqlContainerPerPartitionThroughput `
                    -ResourceGroupName "<resource-group-name>" `
                    -AccountName "<cosmos-account-name>" `
                    -DatabaseName "<cosmos-database-name>" `
                    -Name "<cosmos-container-name>" `
                    -PhysicalPartitionIds ("<PartitionId>", "<PartitionId">)

$allPartitionsDedicatedRUContainer = Get-AzCosmosDBSqlContainerPerPartitionThroughput `
                    -ResourceGroupName "<resource-group-name>" `
                    -AccountName "<cosmos-account-name>" `
                    -DatabaseName "<cosmos-database-name>" `
                    -Name "<cosmos-container-name>" `
                    -AllPartitions

// Database with shared RU/s
$somePartitionsSharedThroughputDatabase = Get-AzCosmosDBSqlDatabasePerPartitionThroughput `
                    -ResourceGroupName "<resource-group-name>" `
                    -AccountName "<cosmos-account-name>" `
                    -DatabaseName "<cosmos-database-name>" `
                    -PhysicalPartitionIds ("<PartitionId>", "<PartitionId">)

$allPartitionsSharedThroughputDatabase = Get-AzCosmosDBSqlDatabasePerPartitionThroughput `
                    -ResourceGroupName "<resource-group-name>" `
                    -AccountName "<cosmos-account-name>" `
                    -DatabaseName "<cosmos-database-name>" `
                    -AllPartitions

确定目标分区的 RU/s

其次,确定要为最热物理分区分配的 RU/s 值。 接下来将此集称为目标分区。 任何物理分区可以包含的最大 RU/s 是 10,000 RU/s。

方法正确与否取决于工作负载要求。 常见方法包括:

  • 将 RU/s 增加一个百分比,测量 429 个响应的比率,然后重复直到达到所需吞吐量。
    • 如果不确定正确的百分比,可以保守一点以 10% 为基础。
    • 如果已知此物理分区需要占用工作负载的大部分吞吐量,则可以先将 RU/s 增加一倍或将其增加到最大 10,000 RU/s,以较低者为准。
  • 将 RU/s 增加到 Total consumed RU/s of the physical partition + (Number of 429 responses per second * Average RU charge per request to the partition)
    • 如果请求没有受到速率限制,此方法会尝试估计“真实”的 RU/s 消耗量。

确定源分区的 RU/s

最后,确定要在其他物理分区上保留的 RU/s 值。 此选择将决定目标物理分区可从中获取吞吐量的分区。

在 PowerShell API 中,必须至少指定一个源分区来从中重新分发 RU/s。 也可以指定重新分发后每个物理分区应具有的自定义最小吞吐量。 如果未指定,默认情况下,Azure Cosmos DB 将确保重新分发后每个物理分区至少具有 100 RU/s。 建议显式指定最小吞吐量。

方法正确与否取决于工作负载要求。 常见方法包括:

  • 从所有源分区平均获取 RU/s(分区 <= 10 个时效果最佳)
    • 计算每个源物理分区所需的偏移量。 Offset = Total desired RU/s of target partition(s) - total current RU/s of target partition(s)) / (Total physical partitions - number of target partitions)
    • 为每个源分区分配最小吞吐量 = Current RU/s of source partition - offset
  • 从最不活跃的分区中获取 RU/s
    • 使用 Azure Monitor 指标和诊断日志来确定哪些物理分区的流量/请求量最少
    • 计算每个源物理分区所需的偏移量。 Offset = Total desired RU/s of target partition(s) - total current RU/s of target partition) / Number of source physical partitions
    • 为每个源分区分配最小吞吐量 = Current RU/s of source partition - offset

第 3 步:以编程方式跨分区更改吞吐量

你可以使用 PowerShell 命令 Update-AzCosmosDBSqlContainerPerPartitionThroughput 来重新分发吞吐量。

为理解下例,我们举一个例子,假设一个容器总共有 6000 RU/s(6000 手动 RU/s 或 6000 自动缩放 RU/s)和 3 个物理分区。 根据分析,所需布局如下:

  • 物理分区 0:1000 RU/s
  • 物理分区 1:4000 RU/s
  • 物理分区 2:1000 RU/s

将分区 0 和 2 指定为源分区,并指定重新分发后两者的最小 RU/s 应为 1000 RU/s。 分区 1 是目标分区,指定它应为 4000 RU/s。

Update-AzCosmosDBSqlContainerPerPartitionThroughput 用于具有专用 RU/s 的容器,将 Update-AzCosmosDBSqlDatabasePerPartitionThroughput 命令用于具有共享 RU/s 的数据库,以在物理分区之间重新分配吞吐量。 在共享吞吐量数据库中,物理分区的 ID 由 GUID 字符串表示。

$SourcePhysicalPartitionObjects =  @()
$SourcePhysicalPartitionObjects += New-AzCosmosDBPhysicalPartitionThroughputObject -Id "0" -Throughput 1000
$SourcePhysicalPartitionObjects += New-AzCosmosDBPhysicalPartitionThroughputObject -Id "2" -Throughput 1000

$TargetPhysicalPartitionObjects =  @()
$TargetPhysicalPartitionObjects += New-AzCosmosDBPhysicalPartitionThroughputObject -Id "1" -Throughput 4000

// Container with dedicated RU/s
Update-AzCosmosDBSqlContainerPerPartitionThroughput `
    -ResourceGroupName "<resource-group-name>" `
    -AccountName "<cosmos-account-name>" `
    -DatabaseName "<cosmos-database-name>" `
    -Name "<cosmos-container-name>" `
    -SourcePhysicalPartitionThroughputObject $SourcePhysicalPartitionObjects `
    -TargetPhysicalPartitionThroughputObject $TargetPhysicalPartitionObjects

// Database with shared RU/s
Update-AzCosmosDBSqlDatabasePerPartitionThroughput `
    -ResourceGroupName "<resource-group-name>" `
    -AccountName "<cosmos-account-name>" `
    -DatabaseName "<cosmos-database-name>" `
    -SourcePhysicalPartitionThroughputObject $SourcePhysicalPartitionObjects `
    -TargetPhysicalPartitionThroughputObject $TargetPhysicalPartitionObjects

完成重新分发后,可以通过查看 Azure Monitor 中的 PhysicalPartitionThroughput 指标来验证更改。 按维度 PhysicalPartitionId 拆分,查看每个物理分区的 RU/s 值。

如有必要,还可以重置每个物理分区的 RU/s,以便容器的 RU/s 均匀分布在所有物理分区中。

Update-AzCosmosDBSqlContainerPerPartitionThroughput 命令用于具有专用 RU/s 的容器,将 Update-AzCosmosDBSqlDatabasePerPartitionThroughput 命令和参数 -EqualDistributionPolicy 用于具有共享 RU/s 的数据库,以在所有物理分区之间均匀分配 RU/s。


// Container with dedicated RU/s
$resetPartitionsDedicatedRUContainer = Update-AzCosmosDBSqlContainerPerPartitionThroughput `
                    -ResourceGroupName "<resource-group-name>" `
                    -AccountName "<cosmos-account-name>" `
                    -DatabaseName "<cosmos-database-name>" `
                    -Name "<cosmos-container-name>" `
                    -EqualDistributionPolicy

// Database with dedicated RU/s
$resetPartitionsSharedThroughputDatabase = Update-AzCosmosDBSqlDatabasePerPartitionThroughput `
                    -ResourceGroupName "<resource-group-name>" `
                    -AccountName "<cosmos-account-name>" `
                    -DatabaseName "<cosmos-database-name>" `
                    -EqualDistributionPolicy

第 4 步:验证和监视 RU/s 消耗量

完成重新分发后,可以通过查看 Azure Monitor 中的 PhysicalPartitionThroughput 指标来验证更改。 按维度 PhysicalPartitionId 拆分,查看每个物理分区的 RU/s 值。

建议监视 429 个响应的总体比率和 RU/s 消耗量。 有关详细信息,请查看第 1 步,验证是否达到了预期性能。

更改后,假设总体工作负载没有改变,则你可能会发现目标和源物理分区的规范化 RU 消耗量都比以前高。 规范化 RU 消耗量更高是预期行为。 基本上,你分配的 RU/s 更接近每个分区实际消耗所需的量,因此规范化 RU 消耗量更高意味着每个分区都在充分利用其分配到的 RU/s。 你还应希望看到 429 个异常的总体比率较低,因为热分区现在拥有更多的 RU/s 来供请求使用。

限制

预览版资格条件

要使用预览版,Azure Cosmos DB 帐户必须满足以下所有条件:

  • Azure Cosmos DB 帐户使用 API for NoSQL 或 API for MongoDB。
    • 如果使用适用于 MongoDB 的 API,则版本必须 >= 3.6。
  • Azure Cosmos DB 帐户使用预配的吞吐量(手动或自动缩放)。 跨分区的吞吐量分布不适用于无服务器帐户。

无需注册即可使用预览版。 要使用此功能,请使用 PowerShell 或 Azure CLI 命令在资源的物理分区之间重新分配吞吐量。

后续步骤

通过以下文章了解如何使用预配吞吐量: