域驱动设计中共享资源的竞争条件

Race conditions over shared resources in domain driven design

问题描述

我正在尝试根据领域驱动设计来实现应用程序,

对于这个问题,假设我们有一个简单的域负责管理某些事件的预订。

每个活动都有参加人数限制,所以系统应该不会允许太多的预订。

预约流程如下:

  1. 从存储库加载事件聚合。
  2. 检查活动是否已满,如果是则停止。
  3. 预订活动
  4. 将事件保存在存储库中。

我的问题是如何解决以下竞争条件:

许多用户可能想同时进行预订,所以我们可能会得到两个并行执行,它们可能会在同一时刻加载事件聚合,两者都看到该事件还有一个空闲槽,并使可能导致预订过多的预订。

这是一个经典的并发问题,但我正在寻找一种适用于 DDD 世界的方法。

我尝试过的想法:

使用数据库的并发控制机制

该过程可以包装在数据库事务中,并用于检测同一事件发生了两次写入。那么一笔交易将失败,我们可以为该用户重试该过程。

我认为它不适合 DDD,因为域层会知道数据库事务,据我所知应该避免这种情况,所有与数据库相关的活动都应该在基础设施层(存储库)中占有一席之地.

应用层并发控制

可以在应用层实现一些并发控制,例如锁定机制,以便在给定事件的同时只执行一次过程。

这对我来说听起来更好,因为我们不基于处理逻辑的数据库实现,而且我们的逻辑模型仍然清晰。

困扰我的是,我们可能只有很少的机器在处理这样的过程,那么我们需要有一些针对这种情况的通用锁定机制。

也许还有其他方法可以解决这种情况? 我愿意接受任何建议。

I think it doesn't fit DDD as the domain layer would be aware of database transactions, which as far as I understand should be avoided, all database-related activities should have a place in the infrastructure layer (repositories).

我不确定您为什么认为在数据库级别强制执行的悲观锁定需要域污染?事务通常在 应用程序层 中管理(可能通过 Unit of Work),因此您可以轻松地应用事务隔离级别来序列化所有事务。

您还可以将乐观并发(带重试)与大多数 ORM 开箱即用支持的版本或完整数据比较一起使用。

你可能需要在模型中引入一个version 属性来支持基于版本的乐观并发,但是这个漏洞可以隐藏在一个中.