2017-04-13 59 views
0

我目前停留在一个问题,希望你能帮助我的一些想法或在这里的最佳实践...事件采购,最终一致,CQRS

比方说,我有使用事件采购和CQRS的应用程序。我有

  • 含有数
  • 含有数
  • 其中I定义的设置,从该锅应显示在UI数红色锅绿色锅。要被显示
  • 包含数字
  • 甲计算结果

我的应用程序的当前状态是

  • 红锅:10
  • 绿色罐20
  • 环境:红
  • 结果:10(来自红罐的值)

我有一个订阅Red Pot服务,Green Pot服务和设置服务的计算服务。我有一个View Updater服务,该服务额外订阅了计算服务,并更新了所有更改的读取模型。

现在下面的事件都在下降:

  1. 绿色盆栽:25
  2. 默认设置:绿色盆栽

的视图更新服务是今天有点忙,并在更新一些延迟视图模型。

Calculation服务处理Green Pot事件。它从读取模型(仍然设置为红色)获取设置,并且不执行任何操作。

之后,Calculation服务处理设置事件。它从读取模型中读取绿色值(仍为20)并发送新事件(结果:20)

之后,View Updater处理两个事件并更新读取模型。

在这种情况下,我的应用程序不一致 - 甚至最终都没有。

有没有想过如何处理这样的事情?感谢您的任何想法:-)

+0

您应该更改事件的名称以更明确,如'GreenPotUpdated','RedPotUpdated'和'SettingsChanged' –

回答

1

首先想到的是,您不清楚您是否共享eventual consistency的共同理解。马丁Kleppmann的talk强调three ideas

  • 交货 - 最终
  • 融合
  • 没有数据丢失

其次想到的是,你似乎已经引入了竞争条件到您的计算服务设计。如果RedPot,GreenPot和Setting是单独的聚合/流,那么它们之间确实没有任何时间绑定。来自这些来源的事件的到来本质上是活泼的。

乌迪大汉写道Race Conditions Don't Exist

定时微秒的差异不应该使核心业务行为的差异。

这就是收敛起作用的地方:您需要设计解决方案,以便即使消息的时间不同,它们也能达到相同的结果。这通常意味着您需要在模型中包含一些时钟或时间的概念,以及某种方式defining the interval in which some result is true

正如你所定义的问题,通过计算服务产生的结果是更多的缓存快照比维护一个历史。因此,考虑您遇到的问题的另一种方式是考虑计算服务不应该接受来自读取模型的任何任意数据,而应该接受它正在消耗的事件。

Calculation service: "Hi, I can haz green pot as of event #40?" 
Read model: "Sorry, no can haz, retry-after: 10 minutes" 
Calculation service: "OK, I'll try again later." 
1

Calculation服务应订阅并接收所有事件(GreenPotUpdated,RedPotUpdatedSettingsChanged)。

Calculation服务不依赖于最终一致的读取模型。相反,它应该保持自己的私人状态,确保以正确的顺序接收事件。