确保您不会使用EventSourcing

时间:2019-12-06 12:37:17

标签: event-sourcing

我想知道您如何确保不在EventStore中两次添加同一个人?

让我们说,在您的应用程序上添加了个人数据,但是您要确保在不同的流中不会两次添加相同的个人姓名和生日。

您问您是ReadModels还是在Evenstore中完成?

2 个答案:

答案 0 :(得分:1)

  

我想知道您如何确保不在EventStore中两次添加同一个人?

您要解决的问题的一般形式是set validation

第1步是严格要求,以确保数据始终唯一-如果数据不必始终唯一,则可以使用检测和纠正方法。参见Pat Helland的Memories, Guesses, and Apologies。粗略地翻译后,您将尽力利用所拥有的信息,如果发现必须还原错误,则进行备份。

如果违反唯一性会使您面临不可接受的风险(例如,由于重复违反了政府规定的隐私要求而被起诉破产),那么您就必须工作。

要验证集合的唯一性,您需要锁定整个集合;在执行中,此锁定可能是悲观的或乐观的。当将整个集合存储在一个位置(也就是说,在一个锁下)时,这相对来说是直截了当的,但是当分布整个集合(又称为多个数据库)时,这是一场噩梦。

如果您的集合是 aggregate (意味着为了更新目的将集合的成员视为一个整体),则DDD的机制很简单。将集合从“存储库”加载到内存中,对集合进行更改,并保留更改。

这种设计适用于事件源,其中每个聚合都具有单个流-您可以通过锁定“该”流来防止种族。

大多数人不希望这种设计,因为集合的成员很大,而且对于大多数数据而言,您只需要这些数据的一小部分,因此将整个集合加载/存储在工作内存中是浪费的。

因此,他们要做的是将维护唯一性属性的责任从域模型转移到存储。 RDBMS解决方案非常擅长使用。您定义维护该属性的约束,并且数据库确保不允许违反该约束的写操作。

如果您的事件存储是关系数据库,则您可以做同样的事情-事件流和维护集合不变性的表在同一事务中一起更新。

如果事件存储区不是关系数据库?好吧,再次,您必须考虑金钱-如果风险足够高,那么您必须丢弃无法让您用能解决问题的管道解决问题的管道。

在某些情况下,还有另一种方法:将需要唯一的信息编码为流标识符。流将代表“所有名为Bob的用户”,然后您的域模型可以确保Bob流一次最多包含一个活动用户。

然后,您开始考虑Bob的名字是否稳定,以及在不稳定的名称更改时您愿意进行哪些权衡。

人名是一个特别痛苦的问题,因为none of the things we believe about names are true。这样您就可以解决所有常见的唯一性问题,最多可以拨11个。

答案 1 :(得分:1)

如果您要验证这种情况,则应在聚合本身IMO中完成,并且您必须像这样说的那样使用使用读取模型。但是您最终将基础结构代码/依赖关系发送到聚合中/传递到方法中。

在这种情况下,我建议创建一个Person.IdPerson.NamePerson.Birthday的读取模型,然后创建一些使用以下内容的服务,而不是直接创建Person读取模型表以查找是否存在一行,然后将其汇总回去,或者创建一个新的并将其还回。然后,只要通过此服务完成所有Person-creation,就完全不需要验证。