Background:
我们有一个EventHub,每天记录数千个事件 . 在新消息到达时,Azure函数在此事件发生时触发器上配置 . azure函数执行以下两项任务:
-
Write
将原始邮件放入文档DB(集合1) -
Upsert
摘要(聚合)消息到文档Db的集合2中 . 在编写消息之前,它会根据partition key
和unique id
(非id)检查摘要消息是否已存在,如果存在doc,则会使用新的聚合值更新doc,如果没有,则插入新的doc . 此唯一ID基于业务逻辑创建 .
Problem Statement:
为PartitionKey和唯一ID创建了多个摘要文档
Scenario Details
-
让我们说,对于PartitionKey
PartitionKey1
,没有在Collection中为计算unique key
创建的摘要文档 . -
多条消息(假设2)到达eventhub并触发了azure函数 .
-
所有这两个请求同时运行,由于没有找到使用该查询的现有文档,因此每个请求都发出一条消息,现在几乎同时调用Upsert函数以通过并发请求编写摘要文档并导致有多个摘要文档对于PartitionKey和唯一ID .
我已经搜索并阅读了 Optimistic Concurrency
,我肯定会实现更新方案 . 但我无法找到可以处理 insert
场景的任何方法?
1 回答
根据您的描述,我建议您使用存储过程来实现此目的 .
Cosmos DB保证作为单个存储过程一部分的所有操作的ACID .
正如官方所说:如果存储过程注册的集合是单分区集合,那么事务的范围限定在集合中的所有文档中 . 如果集合是分区的,则存储过程在单个分区键的事务范围内执行 . 然后,每个存储过程执行必须包括与事务必须在其下运行的范围相对应的分区键值 .
有关Cosmos DB的存储过程以及如何创建存储过程的更多信息,我们可以参考:
Azure Cosmos DB server-side programming: Stored procedures, database triggers, and UDFs
Create and use stored procedures using C#