首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >维护聚合根子实体集合的业务规则一致性和有效性

维护聚合根子实体集合的业务规则一致性和有效性
EN

Software Engineering用户
提问于 2020-06-30 17:58:07
回答 1查看 70关注 0票数 2

假设我们有DailySchedule聚合根和约会实体。DailySchedule AR拥有一组约会。我们的想法是--我们希望执行领域专家提供的以下业务规则:

每天的日程安排不能有两个或多个相同时间的约会(例如,从上午09:00开始,到上午10:00结束)。

现在假设两个用户同时修改每日时间表AR -添加一个新的约会,开始时间为上午09:00,结束时间为上午10:00这两个插入都将成功,因为当最初加载AR和添加新的约会时,业务规则没有被违反,但是最终AR将处于无效状态。

如何才能避免这种情况?我有两个想法:

  1. 悲观的db锁定用户修改AR,而另一个人正在修改它。
  2. 允许AR处于无效状态,并最终以某种方式修复它,某种进程或事件(最终一致性)。
EN

回答 1

Software Engineering用户

回答已采纳

发布于 2020-06-30 19:22:14

这两个插入都将成功,因为当最初加载AR和添加新的约会时,业务规则没有被违反,但是最终AR将处于无效状态。

这是幸运的版本。在不幸的版本中,您将得到一个丢失的编辑:当进行第二个更改时,第一个将被覆盖和丢失。

实际上,这里有两个正交的关注点。第一个问题是更新丢失问题。我们需要确保当我们进行快速编辑时,持久化机制不会破坏信息。

这里通常的机制是锁定;我们确保只有一个进程可以在任何给定的时间保持锁,并确保持有锁的进程保持数据的一致性。

两种常见模式

代码语言:javascript
复制
lock.acquire
db.read
(business logic)
db.write
lock.release

因为读取发生在获取锁之后,所以我们受到保护,以防其他进程偷偷进入并更改刚才读取的数据。

代码语言:javascript
复制
db.read
(business logic)
lock.acquire
db.compare
db.write
lock.release

同样的基本思想:我们确保在任何给定的时间只有一个进程可以写入数据库。这里的不同之处在于,在获得锁之后,我们显式地比较了数据库的状态和我们最初读取的状态。换句话说,我们正在进行比较和交换。

通常使用机械比较;例如,对于每次写入增加版本号;然后,比较只需要检查获得锁后的版本号是否与用于读取数据的版本号相匹配。当然,这确实假设版本的增量与业务数据的更改是同一原子事务的一部分。

完全独立的建模问题是:冲突的任命是被拒绝的,还是应该作为升级来接受和处理。

回顾一下种族条件不存在是很有用的。

时间上的微秒差异不应该对核心业务行为产生影响。

因此,对于像约会日历这样的事情,约会描述了真实世界汤姆逊的状态,并且您有多个协作者向系统提供信息,您可能希望将冲突作为模型的一个显式部分(例如,如果时间时间已经被预定,那么第二个约会可能会进入“等待列表”)。

但是请注意,切换到接受双重预订和升级的模型本身并不修复丢失的编辑错误。您仍然需要锁,以确保第一个约会对第二个约会可见。

票数 2
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/412198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档