并行执行 DocumentDb 存储过程
Executing DocumentDb stored procedures in parallel
documentDb 存储过程 运行 可以并行更新同一个对象吗? documentDb 会按顺序处理它们吗?
考虑以下场景。
我有一个应用程序,我有 10000 个金币可以在我的用户完成任务时赠送给他们。我有以下对象
{
remainingPoints: 10000
}
我有一个存储过程,可以从该对象中减去 10 分并将其添加到用户的分中。
现在假设10个用户同时完成任务,我同时调用存储过程10次,DocDb会顺序执行吗?还是必须顺序执行存储过程?
这将取决于您为 collection 选择的一致性。但是这个想法是,DocumentDb 使用 etag 处理并发,并在文档版本的快照上执行存储过程,只有在执行成功时才提交结果。
参见:https://azure.microsoft.com/en-us/documentation/articles/documentdb-faq/#develop
这个线程也可能有帮助:Atomically increment an integer in a document in Azure DocumentDB
当我第一次开始使用 DocumentDB 时,我也遇到过类似的问题,并在此处和 DocumentDB 产品经理的电子邮件中得到了很好的答案。引用:
Stored procedures ... get an isolated snapshot of the database for transactional support. The snapshot reflects the current state of the world (no stale data) at the time the sproc begins execution (strongly consistent).
Caveat – since stored procedures are operating on a snapshot, you can still get a stale read in a sproc if a new write come in from the outside world during execution.
Also, stored procedures will ALWAYS read their owns writes.
Sprocs are DocumentDB’s mechanism for multi-document transactions. Sproc writes are committed when a sproc successfully complete execution. If an exception is thrown, all work done in a sproc gets rolled back.
So if two are sprocs are running concurrently, they won’t see eachother’s writes.
If both sprocs happen to write to the same document (replace) – then the 2nd one will fail due to an etag mismatch when it attempts to commit writes.
从那以后,我继续我的设计,确保按照@Julian 的建议在我的作品中使用 ETag。我还自动重试每次 sproc 执行最多 3 次,以处理由于并行操作等原因而失败的情况。在实践中,我从来没有超过 3 次重试(除非我的存储过程有错误)而且我什至很少重试一次。
我从我观察到的行为假设它将每个新的存储过程发送到不同的副本,直到它 运行 没有副本,然后将它们排队以顺序执行,所以它是并行的混合体和串行执行。
我通过实验学到的另一个技巧是,当您在负载很重的系统上时,最好在客户端而不是在 sproc 中执行纯读取操作(没有写入和没有显着聚合)。我认为优势是因为 DocumentDB 可以并行地满足来自不同副本的不同读取。我已经使用 expandScript
functionality of documentdb-utils 模块化了我的存储过程代码,以确保我使用完全相同的代码进行写入验证、文档内一致性以及客户端和服务器端的派生字段,这可以使用 node.js。即使您主要使用 .NET,您也可能希望使用 expandScripts
以模块化的 DRY 方式构建存储过程。您仍然需要在构建过程中 运行 node.js 来预处理存储过程或使用 Edge.NET (.NET 中的节点 运行ning)来执行此操作苍蝇。
documentDb 存储过程 运行 可以并行更新同一个对象吗? documentDb 会按顺序处理它们吗?
考虑以下场景。
我有一个应用程序,我有 10000 个金币可以在我的用户完成任务时赠送给他们。我有以下对象
{
remainingPoints: 10000
}
我有一个存储过程,可以从该对象中减去 10 分并将其添加到用户的分中。
现在假设10个用户同时完成任务,我同时调用存储过程10次,DocDb会顺序执行吗?还是必须顺序执行存储过程?
这将取决于您为 collection 选择的一致性。但是这个想法是,DocumentDb 使用 etag 处理并发,并在文档版本的快照上执行存储过程,只有在执行成功时才提交结果。
参见:https://azure.microsoft.com/en-us/documentation/articles/documentdb-faq/#develop
这个线程也可能有帮助:Atomically increment an integer in a document in Azure DocumentDB
当我第一次开始使用 DocumentDB 时,我也遇到过类似的问题,并在此处和 DocumentDB 产品经理的电子邮件中得到了很好的答案。引用:
Stored procedures ... get an isolated snapshot of the database for transactional support. The snapshot reflects the current state of the world (no stale data) at the time the sproc begins execution (strongly consistent).
Caveat – since stored procedures are operating on a snapshot, you can still get a stale read in a sproc if a new write come in from the outside world during execution.
Also, stored procedures will ALWAYS read their owns writes.
Sprocs are DocumentDB’s mechanism for multi-document transactions. Sproc writes are committed when a sproc successfully complete execution. If an exception is thrown, all work done in a sproc gets rolled back.
So if two are sprocs are running concurrently, they won’t see eachother’s writes.
If both sprocs happen to write to the same document (replace) – then the 2nd one will fail due to an etag mismatch when it attempts to commit writes.
从那以后,我继续我的设计,确保按照@Julian 的建议在我的作品中使用 ETag。我还自动重试每次 sproc 执行最多 3 次,以处理由于并行操作等原因而失败的情况。在实践中,我从来没有超过 3 次重试(除非我的存储过程有错误)而且我什至很少重试一次。
我从我观察到的行为假设它将每个新的存储过程发送到不同的副本,直到它 运行 没有副本,然后将它们排队以顺序执行,所以它是并行的混合体和串行执行。
我通过实验学到的另一个技巧是,当您在负载很重的系统上时,最好在客户端而不是在 sproc 中执行纯读取操作(没有写入和没有显着聚合)。我认为优势是因为 DocumentDB 可以并行地满足来自不同副本的不同读取。我已经使用 expandScript
functionality of documentdb-utils 模块化了我的存储过程代码,以确保我使用完全相同的代码进行写入验证、文档内一致性以及客户端和服务器端的派生字段,这可以使用 node.js。即使您主要使用 .NET,您也可能希望使用 expandScripts
以模块化的 DRY 方式构建存储过程。您仍然需要在构建过程中 运行 node.js 来预处理存储过程或使用 Edge.NET (.NET 中的节点 运行ning)来执行此操作苍蝇。