8

您可以使用 CQRS(命令-查询职责分离)架构模式来构建像 StackOverflow 这样的网站吗?我对 CQRS 和 DDD(域驱动设计)相对较新,并且正在探索该模式并尝试为我熟悉该模式的站点建模。虽然我可以看到 CQRS 对于像 StackOverflow 这样的网站的许多方面都很有用,但有一些领域我不确定是否可行(或者,至少,我无法立即弄清楚)。具体来说:

  • 提出问题 当我创建一个问题时,我会立即看到它并且可以对其进行编辑。在 CQRS 中,我发出类似“AskQuestion”的命令,并创建一个名为“QuestionAsked”的事件。最终,问题被推送到非规范化数据存储中。但 SO 的经验是立竿见影的。CQRS 可以做到这一点吗?
  • 投票 我的投票会立即反映。在 CQRS 中,我会想象这些命令/事件最终通过事件总线移动到读取存储。但是 SO 立即给了我信息。

我真正关心的是 SO 提供的即时反馈的概念。CQRS 可以提供这个吗?如果是这样,这将如何完成?有没有很好的例子来说明如何处理这个问题?

如果有帮助,我的环境是 VS2010/C#/SQL2008R2,但我对 SQLite 等其他选项持开放态度。我还在研究 NCQRS 和 LOKAD 的框架,以及 Mark Nijhof 的示例,并计划下载 Greg Young 的示例. 对于 CQRS 样本,我没有找到太多其他内容。

谢谢!

4

4 回答 4

8

让我们看看这两个问题...

提出问题 当我创建一个问题时,我会立即看到它并且可以对其进行编辑。在 CQRS 中,我发出类似“AskQuestion”的命令,并创建一个名为“QuestionAsked”的事件。最终,问题被推送到非规范化数据存储中。但 SO 的经验是立竿见影的。CQRS 可以做到这一点吗?

这很容易实现。是每个用户都需要立即看到问题,还是只需要提出问题的人?如果它需要 1-2 秒才能出现在每个人面前,会有所不同吗?大多数情况下,在最终一致的系统中,发送请求的用户与其他所有用户之间存在差异。

投票 我的投票会立即反映。在 CQRS 中,我会想象这些命令/事件最终通过事件总线移动到读取存储。但是 SO 立即给了我信息。

SO会立即给吗?让我们试试另一个例子,Facebook。当你点赞某样东西时,它会立即出现在你的赞中吗?竖起大拇指之类的 UI 技巧会让您感觉如此。另一个例子,亚马逊。当您单击添加到购物车时,它会立即进入您的购物车吗?诸如“添加到购物车”或“竖起大拇指”之类的视觉表示让您作为用户觉得它已经完成了。

有许多这样的技巧可以使最终一致的系统感觉像是一个完全一致的系统。

作为旁注,许多人认为这些事情是为了可扩展性而做的(有时是这样)。更多时候,它们是为了可靠性而完成的。如果 XYZ 下降,问题就会发生。您想要奇怪的随机本地故障,还是想要冒大范围中断的风险。在这里看到的最好的例子之一是在亚马逊上购买 Kindle,奇怪的是他们可以在 100 毫秒内处理你的信用卡,而其他人需要 3-5 秒 :) 如果他们的信用卡处理系统出现故障会发生什么?

于 2015-08-06T18:08:59.527 回答
6

您实际上在谈论的是“最终一致性”,它经常与 CQRS 同时被谈论,但您可以独立使用任何一种技术。

最简单的做法是立即更新 UI 正在使用的模型,并使用它向用户显示问题以供进一步操作。为了让其他用户可以看到更新,需要完成的各种工作可以在不阻塞 UI 的情况下继续进行。为此,您需要验证您的命令,以便在发送它之前几乎肯定会成功(如果命令在执行期间失败,那么您需要处理这种情况,例如将某种回调合并到 UI 模型) .

还值得记住的是,通常这种事情的“最终性”是如此之快,以至于一切都会立即出现,即使对其他用户也是如此。

于 2010-09-06T12:45:40.427 回答
3

当您提出问题时,您可以在 UI 中“伪造”数据。看起来它已立即更新给用户(您),但其他用户需要一些时间才能看到您的问题。你需要做同样的事情来处理投票。

如果您需要即时反馈,您可以考虑其他解决方案。但是,您可以采取一些技巧在 CQRS 解决方案中提供即时反馈。例如,如果您需要验证用户名是否唯一,您可以查询读取的数据库以查明用户名是否存在。如果没有,您可以使用它。但是,如果其他用户同时选择了相同的用户名,您将在命令端发生冲突。您需要在域模型中处理此问题,例如,为用户提供生成的用户名并通过电子邮件将其发送给他。他可以稍后将其更改为其他内容。

于 2010-09-04T23:35:58.457 回答
1

通过伪造或欺骗,您可能会将事件视为“待处理事件”,在提交/发布阶段可能会成功,但可能会失败。在初始提交提交之前,您在客户端执行的验证越多,成功的可能性就越大。因此,如果您打算依赖待处理的提交,请在验证和业务规则公开方面计划一个更厚的客户端。

然后,可以通过在 UI 中将数据标记或标记为依赖于“待提交”,从而允许用户继续使用数据(以进行进一步修改)。这将是对象或属性的元属性。当然,添加和使用该元属性会增加复杂性,但取决于应用程序可能是必要的用例。

客户端命令队列/历史记录可能是帮助处理后续事件依赖于最终失败的挂起提交的情况的一种方法。换句话说,任何依赖于挂起提交的东西都可以成为历史的一部分,可以在对失败的挂起提交进行更正时进行汇总、保存、再次展开并重新应用于更改和重新提交的挂起事件,并且一旦通知挂起事件提交成功,所有后续客户端历史将开始展开,提交队列中的下一项,将其标记为现在挂起事件。

于 2011-01-22T19:28:10.750 回答