【问题标题】:Entity Framework Concurrency and Azure functions实体框架并发和 Azure 函数
【发布时间】:2018-02-27 06:18:32
【问题描述】:

这个问题可能不仅仅针对 Azure 函数,但对我来说就是场景。我有 azure 函数,它正在处理来自服务总线主题订阅的消息。消息用于在 sql azure 服务器上的表中添加/更新数据。

对于数据库操作,我使用的是实体框架 6.2

我的消息可以是 100 条,但可能只有第一条消息是应该在数据库中插入条目的消息,接下来的几条是同一条记录的更新。

现在,在我的 Azure 函数中,我的 host.json 看起来像这样。

{
 "serviceBus": {
 "maxConcurrentCalls": 16,
 "prefetchCount": 20,
 "autoRenewTimeout": "00:05:00"
}
}

这意味着,它应该能够同时处理 16 条消息,它确实做到了。

但是,通过并发处理,实体框架上下文不会从并行运行的事务中更新,我最终有 10 行,而我应该在数据库中只有 1 行,因为它本质上是相同的记录。

是否有针对此的实体框架特定的解决方案?

【问题讨论】:

  • 我认为你的架构是错误的。您不应该并行化必须以精确顺序处理的活动。或者,如果可行,为每个相关项目添加一个订单号,并在处理之前验证前一个是否已处理。如果否,请重新加入该项目以供将来处理。

标签: c# entity-framework azure azure-sql-database azure-functions


【解决方案1】:

您想要做的是将属于同一实体的消息的处理限制为一次处理 1 条。有几种方法可以做到这一点:

  1. 要在实体框架级别解决此问题,您需要将读写操作正确包装到具有可序列化隔离级别的单个事务中。然而,这并没有多大意义:您对消息进行并行处理,但在数据库级别使用昂贵的锁来限制并行化。

  2. 使用数据库级别的约束,例如唯一索引,然后确保每条消息都为同一实体插入具有相同唯一键的行。尝试写入它的第二个操作将获得约束违反异常,将重试将导致更新的操作。

  3. 只需将maxConcurrentCalls 限制为1,并且永远不要运行多个函数实例。这是最简单的方法,但显然它不适用于更高的负载。

  4. 使用基于实体密钥的服务总线会话,即将相同实体的消息发送到相同会话。不过坏消息:Azure Functions 不支持 Service Bus 会话,因此您必须回退到手动处理。

  5. 使用例如事件中心而不是服务总线订阅。按实体 ID 对事件进行分区,然后按照In order event processing with Azure Functions 中的说明配置您的函数。

【讨论】:

    猜你喜欢
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    相关资源
    最近更新 更多