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

在 Azure Cosmos DB for NoSQL 中跨分区重新分配吞吐量

默认情况下,Azure Cosmos DB 跨所有物理分区均匀分布预配的吞吐量。 但是,如果工作负荷偏斜(例如,某些分区由于热键或流量不均衡而持续需要更多吞吐量),则可以重新分发吞吐量以优化性能。 此功能适用于使用预配吞吐量的数据库和容器(手动或自动缩放),可以使用 Azure Cosmos DB PowerShell 或 Azure CLI 命令进行管理。

例如,如果在零售应用程序中对 StoreId 数据进行分区,则某些商店的活动可能高于其他商店。 如果您注意到这些繁忙商店频繁出现速率限制(429 错误),重新分配吞吐量可以让您向热分区分配更多资源,从而提高性能,而无需增加总吞吐量。

注释

目前,默认情况下,吞吐量提供策略被设置为“等同”。 使用此功能重新分配吞吐量后,策略将被设置为“自定义”,仅允许您通过此 API 更改吞吐量优惠。 通过 Azure 门户更改吞吐量将被阻止,但客户可以将策略更改回“等于”(如下所示),以避免这种情况。

先决条件

  • 现有的 Azure Cosmos DB 帐户
  • 最新版本的 Azure CLI

    • cosmosdb-preview 已安装扩展

      az extension add --name cosmosdb-preview
      
  • 最新版本的 Azure PowerShell

    • 已启用预发行版功能的 Az.CosmosDB 模块

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

使用 Azure Monitor 指标识别热分区

若要使用 Azure Monitor 指标识别 Azure Cosmos DB 中的热分区,请检查每个物理分区的规范化 RU 消耗,以查找使用率不成比例的分区。

  1. 登录到 Azure 门户 (https://portal.azure.com)。

  2. 在 Azure 门户中导航到 Azure Cosmos DB 帐户的 “见解 ”部分。

  3. 选择 “吞吐量”。

  4. 打开按 PartitionKeyRangeID 划分的规范化 RU 消耗量 (%)

  5. 筛选到特定数据库和容器。

  6. 查看每个映射到物理分区的 PartitionKeyRangeId 的图表。

  7. 确定任何始终比其他具有更高规范化 RU 消耗量的 PartitionKeyRangeId。 例如,如果一个值始终为 100%,而其他值则为 30% 或更少,则此模式表示热分区。

    “按 PartitionKeyRangeId 划分的规范化 RU 消耗量”图表的屏幕截图,上面显示一个使用率较高的热分区。

使用诊断日志识别热分区

使用帐户诊断日志中 CDBPartitionKeyRUConsumption 中的信息,了解哪些逻辑分区键和物理分区在二级粒度上消耗了最多的 RU/秒。

  1. 导航到 Azure Cosmos DB 帐户的 “诊断日志 ”部分。

  2. 使用此查询查找随时间推移消耗最多 RU/s 的物理分区(PartitionKeyRangeId)。

    CDBPartitionKeyRUConsumption 
    | where TimeGenerated >= ago(24hr)
    | where DatabaseName == "MyDB" and CollectionName == "MyCollection" // Replace with your database and collection name
    | where isnotempty(PartitionKey) and isnotempty(PartitionKeyRangeId)
    | summarize sum(RequestCharge) by bin(TimeGenerated, 1s), PartitionKeyRangeId
    | render timechart
    
  3. 对于物理分区,请查找使用此查询每小时消耗最多 RU/秒的前 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 your PartitionKeyRangeId
    | summarize sum(RequestCharge) by bin(TimeGenerated, 1hour), PartitionKey
    | order by sum_RequestCharge desc | take 10
    

小窍门

这些示例查询使用 24 小时进行说明,但最好使用至少七天的历史记录来查看使用模式。

确定每个物理分区的当前吞吐量

若要检查每个物理分区的当前 RU/s,请使用 Azure Monitor 指标 PhysicalPartitionThroughput 并按 PhysicalPartitionId 拆分。 如果每个分区的吞吐量从未更改,则通过将总 RU/秒除以物理分区数来估计每个分区的 RU/秒。

使用 az cosmosdb sql container retrieve-partition-throughput 读取每个物理分区上的当前 RU/s。

// Container with dedicated RU/s - some partitions
az cosmosdb sql container retrieve-partition-throughput \
    --resource-group "<resource-group-name>" \
    --account-name "<cosmos-account-name>" \
    --database-name "<cosmos-database-name>" \
    --name "<cosmos-container-name>" \
    --physical-partition-ids "<space-separated-list-of-physical-partition-ids>"

// Container with dedicated RU/s - all partitions
az cosmosdb sql container retrieve-partition-throughput \
    --resource-group "<resource-group-name>" \
    --account-name "<cosmos-account-name>" \
    --database-name "<cosmos-database-name>" \
    --name "<cosmos-container-name>"
    --all-partitions

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

# Container with dedicated RU/s - some partitions
$containerParams = @{
    ResourceGroupName = "<resource-group-name>"
    AccountName = "<cosmos-account-name>"
    DatabaseName = "<cosmos-database-name>"
    Name = "<cosmos-container-name>"
    PhysicalPartitionIds = @("<PartitionId>", "<PartitionId>")
}
$somePartitionsDedicatedRUContainer = Get-AzCosmosDBSqlContainerPerPartitionThroughput @containerParams

# Container with dedicated RU/s - all partitions
$containerAllParams = @{
    ResourceGroupName = "<resource-group-name>"
    AccountName = "<cosmos-account-name>"
    DatabaseName = "<cosmos-database-name>"
    Name = "<cosmos-container-name>"
    AllPartitions = $true
}
$allPartitionsDedicatedRUContainer = Get-AzCosmosDBSqlContainerPerPartitionThroughput @containerAllParams

# Database with shared RU/s - some partitions
$databaseParams = @{
    ResourceGroupName = "<resource-group-name>"
    AccountName = "<cosmos-account-name>"
    DatabaseName = "<cosmos-database-name>"
    PhysicalPartitionIds = @("<PartitionId>", "<PartitionId>")
}
$somePartitionsSharedThroughputDatabase = Get-AzCosmosDBSqlDatabasePerPartitionThroughput @databaseParams

# Database with shared RU/s - all partitions
$databaseAllParams = @{
    ResourceGroupName = "<resource-group-name>"
    AccountName = "<cosmos-account-name>"
    DatabaseName = "<cosmos-database-name>"
    AllPartitions = $true
}
$allPartitionsSharedThroughputDatabase = Get-AzCosmosDBSqlDatabasePerPartitionThroughput @databaseAllParams

注释

有关查找分区数的详细信息,请参阅 缩放预配吞吐量(RU/s)的最佳做法

计算目标分区的吞吐量

接下来,让我们确定要为最热的物理分区分配多少 RU/s(请求单位每秒)。 将此集称为目标分区。

在设置目标分区的吞吐量之前,请记住以下几点:

  • 可以减少或增加分区上的吞吐量。

  • 物理分区最多只能包含 10,000 RU/秒。

  • 用户可以将目标分区的吞吐量设置为最大值 20,000 RU/秒。

    • 将分区设置为大于 10,000 RU/秒的吞吐量值会导致分区拆分,这可能需要一些时间。
  • 如果将分区的 RU/秒设置高于 10,000,它会先获得 10,000 RU/秒。 然后,Azure Cosmos DB 会自动拆分分区,并在新分区之间均匀分配指定的吞吐量。

    • 如果物理分区使用 5,000 RU/秒,并且将其吞吐量设置为 15,000 RU/秒,则 Azure Cosmos DB 首先将 10,000 RU/秒分配给原始分区。 然后,它会将分区自动拆分为 2 个部分,每个最多 7,500 RU/s。
  • 如果所有分区中的最终吞吐量总和不等于当前总产品/服务吞吐量,则此作会相应地更新产品/服务吞吐量。

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

  • 按百分比增加 RU/秒,测量 429 响应的速率,并重复,直到达到所需的吞吐量。

    • 如果你不确定正确的百分比,可以从 10% 开始以保持保守。

    • 如果知道此物理分区需要大部分吞吐量,请首先调整 RU/秒。 将 RU/s 加倍,或将其增加到最大 10,000 RU/秒,以较低者为准。

  • 将 RU/秒增加到 Total consumed RU/s of the physical partition + (Number of 429 responses per second * Average RU charge per request to the partition)

    • 此方法估计如果请求没有速率限制,则“实际”RU/秒消耗量会是什么。

以编程方式更改跨分区的吞吐量

你可以使用 PowerShell 命令 Update-AzCosmosDBSqlContainerPerPartitionThroughput 来重新分发吞吐量。 我们来看一个示例:一个容器的总吞吐量为 6,000 RU/s(手动配置为 6,000 RU/s 或自动缩放到 6,000 RU/s),并且具有 3 个物理分区。 在此示例中,我们需要以下吞吐量分布:

物理分区 RU/s 已分配
0 2,000
1 4,000
2 1,000

重新分发后,总产品/服务吞吐量将从 6,000 RU/秒更新为 7,000 RU/秒。

使用 az cosmosdb sql container redistribute-partition-throughput 更新每个物理分区上的 RU/s。

az cosmosdb sql container redistribute-partition-throughput \
    --resource-group "<resource-group-name>" \
    --account-name "<cosmos-account-name>" \
    --database-name "<cosmos-database-name>" \
    --name "<cosmos-container-name>" \
    --target-partition-info "<PartitionId3=Throughput PartitionId4=Throughput...>"

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

$TargetPhysicalPartitionObjects =  @()
$TargetPhysicalPartitionObjects += New-AzCosmosDBPhysicalPartitionThroughputObject -Id "0" -Throughput 2000
$TargetPhysicalPartitionObjects += New-AzCosmosDBPhysicalPartitionThroughputObject -Id "1" -Throughput 4000
$TargetPhysicalPartitionObjects += New-AzCosmosDBPhysicalPartitionThroughputObject -Id "2" -Throughput 1000

# Container with dedicated RU/s
$containerParams = @{
    ResourceGroupName = "<resource-group-name>"
    AccountName = "<cosmos-account-name>"
    DatabaseName = "<cosmos-database-name>"
    Name = "<cosmos-container-name>"
    TargetPhysicalPartitionThroughputObject = $TargetPhysicalPartitionObjects
}
Update-AzCosmosDBSqlContainerPerPartitionThroughput @containerParams

重新分发后检查吞吐量

完成重新分发吞吐量后,请检查 Azure Monitor 中的 PhysicalPartitionThroughput 指标。 按 PhysicalPartitionId 维度拆分,以查看每个物理分区有多少 RU/s。 如果需要,请重置每个物理分区的 RU/秒,以均匀分布所有物理分区的吞吐量。

重要

重新分发吞吐量后,只能使用相同的重新分发命令更改提议。 若要在所有分区之间均匀分配吞吐量,请使用以下命令。

使用 az cosmosdb sql container redistribute-partition-throughput 和参数 --evenly-distribute 更新每个物理分区上的 RU/s。

az cosmosdb sql container redistribute-partition-throughput \
    --resource-group "<resource-group-name>" \
    --account-name "<cosmos-account-name>" \
    --database-name "<cosmos-database-name>" \
    --name "<cosmos-container-name>" \
    --evenly-distribute 

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

# Container with dedicated RU/s
$containerParams = @{
    ResourceGroupName = "<resource-group-name>"
    AccountName = "<cosmos-account-name>"
    DatabaseName = "<cosmos-database-name>"
    Name = "<cosmos-container-name>"
    EqualDistributionPolicy = $true
}
$resetPartitionsDedicatedRUContainer = Update-AzCosmosDBSqlContainerPerPartitionThroughput @containerParams

# Database with dedicated RU/s
$databaseParams = @{
    ResourceGroupName = "<resource-group-name>"
    AccountName = "<cosmos-account-name>"
    DatabaseName = "<cosmos-database-name>"
    EqualDistributionPolicy = $true
}
$resetPartitionsSharedThroughputDatabase = Update-AzCosmosDBSqlDatabasePerPartitionThroughput @databaseParams

验证和监视吞吐量消耗

完成重新分发吞吐量后,请验证并监视 RU/s 消耗,以确保最佳性能。 执行以下步骤:

  1. 在 Azure 门户中导航到 Azure Cosmos DB 帐户的 “指标 ”部分。

  2. 检查 Azure Monitor 中的 PhysicalPartitionThroughput 指标。 按 PhysicalPartitionId 维度拆分,以查看分配给每个物理分区的 RU/s。

  3. 监视 429 个响应的总体比率和 RU/s 消耗量。

  4. 查看每个分区的 规范化 RU 消耗 量。

    注释

    重新分发后,预期更高的规范化 RU 消耗量,因为 RU/s 分配得更接近每个分区的需求。 有关详细信息,请参阅 标准化的 RU 消耗

  5. 确认 429 异常情况的总发生率已降低。 热分区现在应该有更多的 RU/秒,降低速率限制并提高性能。

局限性

虽然此功能处于预览阶段,但 Azure Cosmos DB 帐户必须满足以下所有条件:

  • Azure Cosmos DB 帐户使用适用于 NoSQL 的 API 或用于 MongoDB 的 API。

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