【问题标题】:CQRS design: nosql data viewCQRS 设计:nosql 数据视图
【发布时间】:2014-12-05 11:37:27
【问题描述】:

这是一个“语言无关”的问题。 我开始研究 CQRS 模式。

我有一个简单的问题。我假设有 2 个不同的存储层:一个用于命令(Mysql 等)的关系层和一个用于“查询”的 NoSql(mongo、cassandra.. 等)?

让我解释一个小例子:

1) 作为用户,我想插入“待办事项” 命令:“创建任务”并将新任务插入到具有用户和待办事项表的数据库中。

2) 作为用户,我可以看到已创建任务的列表 查询:“GetTasks”,它将返回一个“视图”,其中包含从名为“UserTasks”的非 sql 表中获取的任务集合,该表具有用户和已创建任务的列表。

是正确的方法吗?如果语言不好,我很抱歉,这只是一个小例子。 如果这似乎是一个好方法(同样,不要考虑细节)保持更新数据存储的最佳方法是什么?

我正在考虑引发像“TaskCreated”这样的事件并接受新任务并将这些信息插入到 nosql 存储中。

谢谢!

【问题讨论】:

  • CQRS 不需要不同的持久性模型,只需要不同的应用程序模型(域和查询)。根据您的应用程序,您可能会为两种需求使用相同的持久性模型,或者您需要为每种需求使用特定的持久性模型。关键是,这不是必须,您可以选择 1 或 2 个模型是否更适合您的应用
  • 好的,谢谢迈克的回答。是的,如上所述,我知道您可以根据具体情况选择不同的解决方案。如果在某些情况下使用两个不同的数据存储(一个用于命令,一个用于查询)不是“cqrs 设计”违规,我只是好奇。如果不是,在这种情况下,使用“命令”更新查询数据存储的最佳方法是什么?
  • CQRS = 1 个域模型和至少一个读取模型。就是这样。其他任何东西都是实现细节。 CQRS 只是一个原则,您决定如何实施。

标签: domain-driven-design cqrs


【解决方案1】:

我真的不明白你在寻找什么。但是...通常,命令会导致副作用。查询不会引起副作用。 GetTasks 并不是一个命令,而是一个查询。

您的“CreateTask”将是一个命令,它将导致将任务添加到相关数据存储中。您的 GetTasks 查询将从数据存储中检索该信息。如果您为此使用 SQL 或 NoSQL 存储,这并不重要。

“CommandStore”通常是具有足够数据来强制执行不变量的存储。在您的情况下,需要哪些数据?是否需要一些信息来决定是否可以注册任务?例如,假设您要求用户最多可以拥有 3 个“待办事项”。在这种情况下,“Command Store”存储(UserId,Todo Count)中的一个表就足够了。您也可以使用 (UserId, [TodoId]) - 即。存储一个 todo id 列表,以便获得幂等性。有关用户和任务的所有其他信息都是查询数据,并且会在查询存储中。

希望这是有道理的。

【讨论】:

  • 您好,感谢您的回答。是的“getTask”是一个查询(我立即修改了这个错误,因为我称它为“CommandQuery”,我的意思只是一个查询“。我的问题是,是否有意义或没有将信息存储在 sql 数据库中(来自命令的信息) 同时拥有该信息的 NoSql 视图。nosql 视图是查询的存储,信息以“查询驱动”的方式建模。有意义吗?
  • 同样,sql 或 nosql 并不一定重要。重要的是命令端存储应该只包含强制执行不变量所需的信息。这可能意味着查询存储中的某些信息,或者它可能完全采用完全独立的格式。这取决于您的特定业务场景。
  • 好的,谢谢!可能我没有很好地解释我的意思。我只是说:假设如果有一个业务场景,命令将信息存储在 STOREA 中。并假设查询从 STOREB 获取信息。其中 STOREA != STOREB 因为在 STOREB 中的信息以另一种方式组织,使 STOREB 与 STOREA 保持更新的最佳方法是什么?我认为 CQRS 的好处之一是“写”之间的关注点分离”动作和“读取”动作。然后,在某些情况下,我可以将写入或读取数据的存储区分开。
  • 有很多方法,具体取决于保证、延迟等。如果您需要 A 和 B 之间的绝对一致性,则必须使用某种形式的支持 3 阶段提交的事务协调器(假设 A 和 B 之间有一个网络)。很多时候,使用消息队列/总线......更新A并发布消息。处理程序更新 B。另一种方法是发布消息,单独的处理程序更新 A 和 B。另一种方法是发布事件,处理程序轮询以更新视图模型存储。例如,这可以通过 ATOM。很多选择。
【解决方案2】:

虽然有时您可能希望存储命令,但通常不会。一种流行的方法是存储由于命令而发生的域事件。这称为事件溯源。这将使“STOREA”成为事件存储,或者换句话说,事件流。 'STOREB' 通常被称为读取模型。它具有针对读取速度优化的非规范化结构。它通过响应特定事件的去规范化器保持最新。这里要注意的一个关键点是,在引发事件和更新读取模型之间通常存在延迟。我认为这是一件好事,但在设计 UI 时需要考虑。

更多信息请查看CQRS – A Step-by-Step Guide to the Flow of a typical Application

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2012-12-08
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 2022-11-14
    • 1970-01-01
    相关资源
    最近更新 更多