【问题标题】:Issue Insert/Update EF Core DbContext in Azure QueueTrigger Function (Multi-threading)在 Azure QueueTrigger 函数(多线程)中问题插入/更新 EF Core DbContext
【发布时间】:2018-10-16 07:57:19
【问题描述】:

Azure QueueTrigger 函数中使用 EF Core 2.1 DbContext 时出现 PK 违规异常。猜测是由于 DbContext 的性质不是线程安全,并且 Azure 函数并行运行不同的实例。我已经阅读了很多,但我找不到解决这个问题的好方法。

这是我的场景(生产者-消费者模式):

我有一个 Scheduled Azure Function,它正在调用 API 以从不同的外部系统获取项目。要获取项目所需的所有信息,我需要对其他外部服务运行不同的查询,因此我将其与另一个 Azure 函数解耦,因此计划函数只是将每个项目的消息排队,如“同步项目” ID 101”。

另一个QueueTrigger函数在每次消息排队时触发,因此,这意味着不同的实例并行运行。此函数必须收集特定 Project 的所有数据,这意味着对其他外部服务/API 的更多调用,以(某种)聚合有关 Project 的所有信息>。恕我直言,这样做很好,因为我可以并行处理多个项目,并且可以根据需要扩展功能。

获得所有这些项目信息后,我想使用 EF Core 将其保存在 SQL DB 中(问题来了)

项目数据包括项目中的用户,每个用户都有一个特定的 GUID 作为 PK(来自外部系统)。这意味着我可以在不同的函数实例中重复用户 ID,这就是问题所在,因为当我尝试将用户信息保留在 SQL 表中时,我可以得到 PK 重复异常,因为多个函数实例可以尝试插入同一个用户同时(当实例A检查用户是否存在时,它得到了False,但另一个实例B实际上正在添加这个用户,所以当实例A尝试插入时,它失败了)。

我想我可以以某种方式锁定 DbContext,但不确定是否好用,因为我还有一个网站对 SQL DB 进行查询(目前是只读查询,但将来也可能会更新)。

另一个想法可能是将整个项目信息发送到另一个队列 / Blob 文件,并在 单例 模式下具有另一个功能,将数据插入 SQL。

我创建了这个项目来简化我的场景,但足以重现问题并理解问题。 https://github.com/luismanez/queuetrigger-efcore-multithreading

还有其他想法或推荐的方法吗? (如果发现更好的东西,可以改变架构)

非常感谢!

【问题讨论】:

标签: entity-framework-core azure-functions entity-framework-core-2.1


【解决方案1】:

一种“更简单”的方法可能是在数据库中执行某种 upsert。有一个如何使用 EF Core 执行此操作的示例:https://www.flexlabs.org/2018/02/adding-upsert-support-for-entity-framework-core

【讨论】:

  • 谢谢塞巴斯蒂安,看起来是个不错的方法。最后,我使用 Durable 函数扇出/输入模式更改了我的架构,因为它在我的场景中更有意义,并且还解决了这个问题,因为持久数据进程正在串行运行。但是,标记您的答案,这似乎是对原始问题更具体的有效方法。虽然没有测试过。非常感谢!
  • 好的。请注意 Durable 函数,因为它们使潜在的并发问题比经典工作流更难以预测。在扇出场景中,问题更难追踪。 (我自己对持久功能的经验)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 2021-07-04
  • 2021-11-23
  • 2021-01-06
  • 2018-09-22
  • 1970-01-01
  • 2019-08-24
相关资源
最近更新 更多