假设我们有DailySchedule聚合根和约会实体。DailySchedule AR拥有一组约会。我们的想法是--我们希望执行领域专家提供的以下业务规则:
每天的日程安排不能有两个或多个相同时间的约会(例如,从上午09:00开始,到上午10:00结束)。
现在假设两个用户同时修改每日时间表AR -添加一个新的约会,开始时间为上午09:00,结束时间为上午10:00这两个插入都将成功,因为当最初加载AR和添加新的约会时,业务规则没有被违反,但是最终AR将处于无效状态。
如何才能避免这种情况?我有两个想法:
发布于 2020-06-30 19:22:14
这两个插入都将成功,因为当最初加载AR和添加新的约会时,业务规则没有被违反,但是最终AR将处于无效状态。
这是幸运的版本。在不幸的版本中,您将得到一个丢失的编辑:当进行第二个更改时,第一个将被覆盖和丢失。
实际上,这里有两个正交的关注点。第一个问题是更新丢失问题。我们需要确保当我们进行快速编辑时,持久化机制不会破坏信息。
这里通常的机制是锁定;我们确保只有一个进程可以在任何给定的时间保持锁,并确保持有锁的进程保持数据的一致性。
两种常见模式
lock.acquire
db.read
(business logic)
db.write
lock.release因为读取发生在获取锁之后,所以我们受到保护,以防其他进程偷偷进入并更改刚才读取的数据。
db.read
(business logic)
lock.acquire
db.compare
db.write
lock.release同样的基本思想:我们确保在任何给定的时间只有一个进程可以写入数据库。这里的不同之处在于,在获得锁之后,我们显式地比较了数据库的状态和我们最初读取的状态。换句话说,我们正在进行比较和交换。
通常使用机械比较;例如,对于每次写入增加版本号;然后,比较只需要检查获得锁后的版本号是否与用于读取数据的版本号相匹配。当然,这确实假设版本的增量与业务数据的更改是同一原子事务的一部分。
完全独立的建模问题是:冲突的任命是被拒绝的,还是应该作为升级来接受和处理。
回顾一下种族条件不存在是很有用的。
时间上的微秒差异不应该对核心业务行为产生影响。
因此,对于像约会日历这样的事情,约会描述了真实世界汤姆逊的状态,并且您有多个协作者向系统提供信息,您可能希望将冲突作为模型的一个显式部分(例如,如果时间时间已经被预定,那么第二个约会可能会进入“等待列表”)。
但是请注意,切换到接受双重预订和升级的模型本身并不修复丢失的编辑错误。您仍然需要锁,以确保第一个约会对第二个约会可见。
https://softwareengineering.stackexchange.com/questions/412198
复制相似问题