使用多个实例时的 EF 核心并发

EF core concurrency when using multiple instances

我有类似的代码:

var records = db.Records.Where(r => r.IsProcessing == false).Take(100).ToList();
records.IsProcessing = true;
await db.SaveChangesAsync()
...further work with recods

如果这段代码运行在一个微服务的多个实例上,会不会出现并发问题? (即两个服务将获得相同的记录集)。如果是 - 我该如何预防?

我想防止我的服务在同时调用此方法时从数据库中获取相同的记录。

是的,它会发生,而且要防止它可能并不那么容易。

想象一下,这些服务的任务是更新账户余额。 他们读取余额,并在上面添加存款金额:

service 1: on a busy machine (slow)
service 2: on a not so busy machine (fast)
"john" has £100 on his account
service 1: read
service 2: read
service 1: balance = balance + 100;
service 2: balance = balance + 100;
service 2: set processing = true
service 2: set processing = true
service 2: update record
service 1: update record.
john ends up with £200 instead of £300.

你需要引入一个事务作用域,也许用redis来管理它, 这样每个实例都有一个真实点来检查是否可以进入和退出更新范围。如果您愿意,可以通过网络“IsProcessing?或 SetIsProcessing”。

您可以在可序列化事务中使用存储过程检索行,运行。您可能需要 table 中的其他属性,例如 AssignedTo 记录分配给该行的服务,以及另一个指示处理已完成的属性。否则,如果服务检索到某些行但在完成所有处理之前失败,则这些行将保持未处理状态。当服务检索行时,它可以使用类似 AssignedTo = self 或 AssignedTo Is Null 的条件。大概还有时间戳或其他方式来确定所选行的优先级。