DDD使用NoSQL处理最终上下文内多个聚合的最终一致性

时间:2018-08-09 18:50:21

标签: events redis event-handling domain-driven-design mediator

我目前正在开发DDD Geolocation应用程序,该应用程序在一个有界上下文中具有两个单独的聚合根。由于坐标经常更新,因此我使用Redis保留数据,这不允许回滚。

  1. 我的第一个汇总根是包含驾驶员(用户),乘客(用户列表)等的旅行对象。
  2. 我的第二个汇总根是用户位置更新

发送坐标更新后,我将生成并触发“ UpdateUserPostionEvent”。作为副作用,我还将在特定点生成并触发“ UpdateTripEvent”,这将更新驾驶员/乘客的坐标。

我的问题是,如果我异步触发“ UpdateLiveTripEvent”,如何处理最终的一致性。我的UpdateLiveTripEventHandler有几个故障点,除了记录错误外,如何处理这种不一致?

我正在使用一个名为MediatR的库和一个INotificationHandler,据我所知,它是“ Fire and Forget”

编辑:最终找到了准确描述我需要的SO post(传奇/流程经理),但不幸的是,我无法找到用于处理事件的任何Saga形式同一BC。我看到的所有示例都涉及到服务总线。

1 个答案:

答案 0 :(得分:2)

相同或不同的有界上下文;有或没有Sagas;没关系。

为什么事件处理失败?域规则或基础架构。

域名规则: 绝对不会因域规则失败而由聚合处理的引发事件(事件处理程序使用聚合来应用事件)。

如果“目标”聚合具有拒绝该事件的域规则,那么您的聚合设计错误。域规则可以拒绝命令/操作。域规则不能拒绝(也不能撤消)事件。

当“起源”聚合检查了此操作的所有域规则时,应引发一个事件。 “目标”集合应用该事件,并可能引发另一个事件,该事件具有由“目标”集合计算的某些值(域规则,但不能拒绝该事件;事件不能被域规则拒绝;而是要“继续”一致性“链” ”(责任隔离)。这就是为什么事件过去应该使用句子作为名称的原因;因为已经发生了。

事件模拟:

  • Agg1:嗨,哥们!用户做了一件很酷的事情,一切似乎都还可以。 -> UserDidThisCoolThingEvent
  • Agg2:哇,太棒了!我要在用户点数上加上+3。 -> UserRecibedSomePointsEvent
  • Agg3:+3指向该用户?用户仅达到100分。好多!我要将该用户转换为VIP用户。 -> UserTurnedIntoVIPEvent
  • Agg4:新的VIP用户?让我们通知其他用户以创建理智的嫉妒;)

基础设施: 修复它并应用该事件。 ;)持久性引擎,网络和/或计算机再次启动后,即使需要也可以手动操作。

短时间自动重试失败。 ErrorQueues / Logs在长时间中断时不会丢失事件(以后再应用)。

事件源还可以帮助您解决此问题,因为您可以始终在“目标”聚合中重新应用持久性事件,而无需付出额外的努力就可以将事件保留在某个地方(例如事件日志),因为您的域持久性也是您的事件存储。