Kun*_*pta 6 azure azure-cosmosdb
我对 cosmos DB 相当陌生,并试图了解azure cosmos DB SDK 为 Java 提供的用于修补文档的增量操作。我需要在容器中的文档之一中维护增量计数器。该文件看起来像这样——
{"counter": 1}
Run Code Online (Sandbox Code Playgroud)
现在,在我的应用程序中,每次发生操作时,我希望将此计数器的值增加 1。为此,我使用CosmosPatchOperations。我在这里添加一个增量,这样cosmosPatch.increment("/counter", 1)效果很好。
现在,该应用程序可以运行多个实例,所有实例都与 Cosmos 容器中的同一文档进行通信。所以App1和App2都可以同时触发增量。SDK 方法返回更新后的文档,我需要使用该更新后的值。
我的问题是,这里的 cosmos DB 是否采用某种锁定机制来确保两个补丁相继发生,并且在这种情况下,我在 App1 和 App2 中获得的更新值是什么(SDK 方法返回更新后的值)文档)。其中一个是 2 个,另一个是 3 个吗?
Couchbase 在集群级别支持这样的计数器,如此处所述,它对我来说工作得很好,没有任何并发问题。我现在正在迁移到 cosmos Db,并一直在努力寻找如何实现这一目标。
更新1:
我决定测试一下。我在本地 Mac 中设置了 Cosmos 模拟器,并创建了一个 DB 和容器,并且 RU 会自动从 1 增加到 10K。然后在这个容器中我添加了一个像这样的文档 -
{
"id": "randomId",
"counter": 0
}
Run Code Online (Sandbox Code Playgroud)
在此之后,我创建了一个简单的 API,其职责只是在每次调用时将计数器加 1。然后我使用Locust多次调用这个 API 来模拟一个小型的类似负载的场景。最初,测试运行良好,每次调用都像预期的那样接收计数器(以增量方式)。在增加负载时,我看到一些错误,即RequestTimeOutException,状态代码为 408。其他请求仍然可以正常工作,并获得正确的计数器值。我不明白是什么导致了这里的 RequestTimeOut 异常。堆栈跟踪暗示与并发有关,但我无法理解它。这是堆栈跟踪 -
更新 2: 更新 1 中的测试运行是在我的本地计算机上完成的,我意识到我的本地计算机上可能存在资源问题,导致这些错误。决定在预生产环境中使用实际的 cosmos DB 而不是模拟器来测试这一点。
测试配置-
发现-
直到约 170 TPS,一切都运行顺利。除此之外,我注意到属于 2 个不同桶的错误 -
我不确定 170 个奇怪的补丁操作如何会耗尽 4000 个 RU,但这完全是一个不同的讨论。
此错误清楚地表明 cosmos DB 不处理并发请求。我想了解他们是否在内部维护一个队列来处理某些请求,或者他们根本不处理任何并发写入。
PATCH 与其他操作没有什么不同,CosmosDB 从根本上实现了乐观并发控制,这与具有这些机制的关系数据库不同。乐观并发控制 (OCC) 允许您防止更新丢失并保持数据正确。OCC可以通过文档的etag来实现。Azure Cosmos DB 中的每个文档都有一个E_TAG属性。
在您的场景中,是的,如果两者都成功,它将在其中一个返回 2 ,在另一个返回 3 ,因为 SDK 有重试机制,并在此处进行了解释。另请查看此示例。
如果 Azure Cosmos DB 帐户配置了多个写入区域,则冲突和冲突解决策略适用于文档级别,最后写入优先 (LWW) 是默认冲突解决策略
| 归档时间: |
|
| 查看次数: |
1674 次 |
| 最近记录: |