我很新的CosmosDb,但很快我遇到了一个问题,我从来没有使用MS SQL时。
目前,我们有一个操作,在此期间,我们以10万个为批量更新数百万个CosmoDb项。在此操作过程中,我注意到App insights中约有25%的请求显示为429ns。根据微软文档,429个请求中有1-5%是健康的,超过这个比例就是问题了。
现在我已经尝试了不同的方法来降低这个数字,而不必扩展吞吐量,但没有任何帮助。我不确定这是否是我的测试实现的问题,因为我尝试了不同的东西,可能在某个地方犯了错误。
测试设置:
- 数据库有5个不同的容器。每一个都是单独缩放的。运行测试的容器在3000 RU/s的最大吞吐量下自动缩放
- 容器有大约170 k资产,大小为0.5 Gb
- CosmosClient是一个单例
- 3000项在测试期间以1000个批次更新
浴槽操作代码:
var updateTasks = new List<Task>();
// queriedItems will have 1000 items in each batch
foreach (SomeCosmosbDbModel queriedItem in queriedItems)
{
queriedItem.SomeProperty = someValue;
updateTasks.Add(_repository.UpdateAsync(queriedItem));
}
await Task.WhenAll(updateTasks);
更新方法代码:
public Task UpdateAsync(TModel model)
{
return Container.ReplaceItemAsync(model,
model.Id,
new PartitionKey(model.Partition),
new ItemRequestOptions { EnableContentResponseOnWrite = false });
}
以下是我试图降低429ns数量和结果的事情:
- 使用补丁而不是更新操作。我认为它应该比更新操作轻一点->429s %无差异
- 检查分区键是否没有问题。如果我正确理解分区是如何工作的,如果数据库很小,RU/s的数量低于10,000,它应该对这个测试没有影响- doc
- 使用BulkUpdate方法->类似的数字是429ns。它也导致了一些FailedReindexExceptions与TooManyRequests(429)错误,在这种情况下,一些项目实际上没有得到更新(约8%)
- 将项目索引更改为none ->对429ns无影响
现在看来,所有的改变都可以提高操作的速度,但每次它都达到了容器上的ru的限制,在某些情况下,它实际上导致不执行一些写操作并抛出异常。
我能做些什么来降低429ns的数量吗?或者如果我没有在考试中出错,我应该再检查一下我已经做过的事情?此外,是否建议在生产应用程序中使用自定义RetryPolicy来提高弹性?
更新需要一定数量的RU,您几乎无法控制(除了索引策略)。因此,要减少429的数量,您唯一的选择是降低吞吐量。
如果这是您在数据库上运行的唯一工作负载,那么只要您的RetryPolicy
能够尝试并且足够长时间直到它最终工作,我就不会太担心它抛出429。理论上,您的重试策略应该能够处理在开始附近和上传所有其他文档时失败的请求;因此,您的RetryPolicy
应该包含大量重试和超时,该超时超过了上传批处理所需的最大时间。
如果其他进程也在使用您的数据库,那么最好考虑限制您发送的请求数量,这更复杂,但也是可行的。每个响应都包含使用的RU,这允许您通过在请求之间添加Task.Delay(...)
来非常精确地调整吞吐量。
我不会太担心1-5%的暗示。这主要是针对平均数据库使用率,而不是批量导入。