使用模式读取CQRS模式中的“最新数据”+事件源

时间:2016-04-20 01:23:28

标签: .net cqrs event-sourcing

我正在使用CQRS(Command Query Responsibility Segregation)模式实现测试项目。

我有几个问题。

  1. 我想在购买之前检查用户购物车上商品的数据存储的最新价格。因此,将根据数据存储(产品表)上的最新价格检查real_model(通过物化视图)价格。如果价格之间存在差异,我想向用户显示警报。实现这一目标的最佳方法是什么?

  2. 当用户更新其电子邮件和密码时,它是否仍然依赖于创建事件来更新DataStore(Event-> EventStore-> Service Bus-> DataStore)或直接更新数据存储?我不希望事件的延迟触发read_model_update,因为用户必须立即重新登录。

1 个答案:

答案 0 :(得分:3)

  

我想在购买前检查用户购物车上商品的数据存储的最新价格...实现这一目标的最佳方法是什么?

我怀疑是实现这一目标的最好方法。很大程度上取决于您的利益相关者希望提供给客户的购物体验。 IE - 什么时候应该锁定价格?例如,购物车中显示的价格可能是具有时间限制的确定报价。

但是删除那些细节......

一种方法是在调度命令之前对读取模型运行健全性检查。有一种常见的模式(有效地)检查命令是否可以在读取模型的状态下工作,然后调度临时验证的命令来更新记录簿。您可以通过一些延迟来降低故障率。

另一种可能性是使用流程管理器;这个想法是" placeOrder"不是对模型的简单写入,而是生命周期的开始。因此,想象一下例如价格报价是模型中的一个东西 - 当一个项目放在购物车中时,会生成一个价格报价(可能带有一些到期值)。当价格变化时,所有不同的报价都会得到更新。下订单时,处理程序会看到placementOrder事件,并尝试在价格报价上调用acceptQuote方法;如果报价仍然有效,则生成的事件会将订单流程推进到下一个状态。如果报价不再有效,则会生成不同的事件,或者命令被拒绝,最终超时会显示可能存在问题....

(您可以尝试与产品本身做类似的事情,但由于争用问题而无法正常工作;了解您正在使用 最新状态的唯一方法对象的一个​​对象是对记录簿接受的写入。)

Udi Dahan审核Race Conditions Don't Exist可能会有用。

  

当用户更新其电子邮件和密码时,它是否仍然依赖于创建事件来更新DataStore(Event-> EventStore-> Service Bus-> DataStore)或直接更新数据存储?

没有直接更新 - 读取模型的所有更新都应该在更新到记录簿之后发生。

  

我不希望延迟触发read_model_update的事件,因为用户必须立即重新登录。

用户可以立即重新登录,但这并不意味着您需要立即确认登录。

例如;通过写模型,您刚刚发布了一系列新事件。获取已发布的最高事件的序列号,并将查询的那部分分配给读取模型;登录处理程序根据读取模型中可用的内容检查序列号,如果模型需要另一个心跳来赶上,则会停止。

(更有可能的是:在这种用例中,您在事件发布系统和客户端的后续请求之间进行了竞争,您将安排一个将查询事件存储的读取模型因此,您的延迟基本上取决于读取模型和记录系统之间的网络距离,加上应用新事件所需的时间。实际上,来自客户端的请求用作指示事件消息。高水位标记增加,然后模型调度查询以获取缺失的历史记录。

还要注意推论 - 读模型的不同部分有不同的延迟要求。

CQRS是一种贝壳游戏。仍然只有一个记录系统,持久性存储接受模型的写入。该存储针对写入进行了优化。读模型可以附加到该存储(获取最新的可用数据,但由于数据处于"写优化"形式),或者对该存储的投影(数据较旧,但已针对特定读数进行了优化)。