CQRS和最终一致性

时间:2018-08-20 20:33:58

标签: cqrs eventual-consistency

我已添加到正在开发的项目中。这是一个使用Mediatr和CQRS模式的ASP.Net MVC 5应用程序(具有只读数据库和只写数据库-最终保持一致)。该应用程序的管理部分包含许多CRUD操作,我们遇到了问题。例如,假设有一个窗口小部件控制器:

data

在“创建”和“编辑”操作中,将创建或编辑窗口小部件,并对只读数据库进行那些更改。这之后是立即重定向到索引操作,该操作将从只读数据库读取。通常,在此调用完成并呈现视图时,更改不会从只写数据库同步。要解决此问题,我们已使用Redis缓存新创建或更新的对象,然后,如果在Index操作中检索到的列表不包含新对象或已编辑对象,则从缓存中检索它。 这感觉确实非常错误。

由于我们这个项目的所有人都没有参与过CQRS项目,因此我们不知道如何解决此问题。感觉我们真的缺少这种模式。

所以,我想我要问的是...是否存在处理此类情况的最佳实践?有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

在CQRS中,写入持久性和读取持久性是分开的(在逻辑上,在时间上,甚至在物理上),并且您所经历的是正常的,您应该接受这一点,而不应将其视为基本问题。相反,您应该修改您的客户端以对此进行补偿。例如,您应该拨打电话以在后台(即AJAX)更新实体,而不是将客户端重定向到编辑页面。这是最简单的解决方案之一。其他则更为复杂,例如使用相关性或cauzal标识符,上次修改的时间戳,在应用程序或表示层中等待读取模型处理事件等。

答案 1 :(得分:1)

关于how to handle the eventual consistency的非常快速的搜索。在我的项目中,我们主要依靠websocket通知(即SignalR),但是有时“假响应”已经足够了。

我想知道为什么使用CQRS,专门用于CRUD操作。看来您是否过度设计了您的设计。 Asyncronicity comes with a lot of issues to face

答案 2 :(得分:1)

  

所以,我想我要问的是...是否存在处理此类情况的最佳实践?有更好的方法吗?

您需要的许多零件已经准备就绪。

关于CQRS的一种思考方式是,写操作针对域模型的实时表示,而读操作针对缓存表示。

HTTP对caching有很好的理解。特别是,HTTP感知缓存了解不安全操作invalidate缓存了表示。因此,对POST请求的任何非错误响应都会使缓存的数据无效。

您甚至拥有用于处理最终一致性的状态码; 202 Accepted向中介宣布该请求不是错误(使高速缓存无效),但“处理尚未完成”。就像200 response一样,有效负载是“动作状态的表示”。

因此,您可以向客户端发送“ 202已接受”,并带有指向状态监视器的链接,该链接具有了解读取模型是否已更新的必要信息。例如,写模型可能知道您正在等待的对象的“版本”,或者有多少事件(如果您正在执行事件源),或者帖子本身是correlation identifier
  将此元数据编码到状态监视器的目标资源中,客户端可以轮询状态监视器,直到指示读取的模型已更新。

甚至对弱验证器都有了解,修改操作可以返回该弱指示符,以指示资源的版本,而无需了解强验证器所需的表示形式的详细信息。

但是...我承认我没有发现零件的组合会产生令人满意的整体。感觉好像缺少了一部分-使我们可以返回带有动作状态表示形式的验证器,以帮助客户提出适当的条件请求以读取表示形式。