我目前陷入困境,希望你能在这里帮助我提出一些想法或最佳做法......
假设我有一个使用Event Sourcing和CQRS的应用程序。我有
我的申请的当前状态是
我有一个计算服务,订阅Red Pot服务,Green Pot服务和设置服务。我有一个View Updater服务,它还可以订阅Calculation服务,并在任何更改时更新读取模型。
现在发生以下事件:
View Updater服务今天有点忙,并且在更新视图模型方面有一些延迟。
计算服务处理Green Pot事件。它从读取模型(仍然设置为红色)获取设置,并且不执行任何操作。
之后,Calculation服务处理Settings事件。它从读取读取模型中获取绿色值(仍为20)并发送新事件(结果:20)
之后,View Updater会处理这两个事件并更新读取模型。
在这种情况下,我的申请不一致 - 甚至最终都没有。
有任何想法如何处理这样的事情?感谢您的任何想法: - )
答案 0 :(得分:1)
Calculation
服务应订阅并接收所有活动(GreenPotUpdated
,RedPotUpdated
和SettingsChanged
)。
Calculation
服务依赖于最终一致的读取模型是不行的。相反,它应该保持自己的私有状态,确保以正确的顺序接收事件。
答案 1 :(得分:1)
首先想到的是,您并不清楚您是否正在分享对eventual consistency
的共同理解。 Martin Kleppmann的talk强调three ideas
第二个想法是,您似乎已在计算服务设计中引入了竞争条件。如果RedPot,GreenPot和Setting是单独的聚合/流,那么它们之间实际上没有任何时间绑定。来自这些来源的事件的到来本质上是充满活力的。
Udi Dahan写了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."