【问题标题】:Does a CQRS project need a messaging framework like NServiceBus?CQRS 项目是否需要像 NServiceBus 这样的消息传递框架?
【发布时间】:2012-10-14 08:30:50
【问题描述】:

过去 6 个月的学习曲线一直充满挑战,CQRS 和 DDD 是罪魁祸首。

这很有趣,我们的项目已经完成了 1/2,而我没有时间深入研究的领域是消息传递框架。

目前我不使用 DTC,所以很有可能如果我的读取模型没有更新,那么我将在读取和写入数据库之间出现不一致。我的读写数据库也将在同一台机器上。我怀疑我们是否会将它们放在不同的机器上。

我的系统中没有大量消息,因此我更关心的是系统的一致性和可靠性。

那么,我是否必须放入像 NServiceBus 这样的消息传递框架(即使读写数据库都在同一台机器上)还是我有其他选择?是的,有学习曲线,但我想如果我不使用它,我会学到很多东西。

另外,如果没有必要,我不想放一个层

想法?

【问题讨论】:

    标签: nservicebus cqrs masstransit


    【解决方案1】:

    目前我不使用 DTC,所以很有可能如果 我的读取模型没有更新,那么我之间会有不一致 读写数据库。

    就我个人而言,我不喜欢 DTC 并尽量避免它。相反,通常可以实现补偿机制,特别是对于最终一致性已经可以接受并且更新是幂等的读取模型之类的东西。例如,您可以在实体上实现一个版本,并拥有一个确保版本同步的后台任务。拥有 DTC 将提供事务重试功能,但它仍然无法解决重试后发生故障的情况 - 您仍然必须查看错误日志并制定处理错误的程序。

    那么,我是否必须放入像 NServiceBus 这样的消息传递框架(甚至 虽然读写数据库都在同一台机器上)还是我 还有其他选择吗?

    这取决于几件事。您在 CQRS 系统中经常遇到的是需要 pub/sub,其中几个子系统发布查询/缓存系统订阅的事件。如果您发现除了基本的点对点消息传递之外还需要发布/订阅,那么请使用 NServiceBus 之类的东西。此外,即使您出于可扩展性目的不需要它,我也不会立即回避使用 NServiceBus,因为我认为逻辑分区本身是有益的。另一方面,正如您所指出的,增加复杂层的成本很高,因此首先尝试看看最简单的方法是否可行。

    另一个要问的问题是您是否需要一个单独的查询存储。如果你只有一台机器,为什么还要麻烦?您可以使用像 read-model pattern 这样更简单的东西,并且仍然可以获得 CQRS 的很多好处。

    【讨论】:

    • 非常感谢您提供的信息。我将看一下读取模型模式。您提到实体上的版本,您的意思是聚合根或事件上的版本?
    【解决方案2】:

    CQRS 项目是否需要像 NServiceBus 这样的消息传递框架?

    简短的回答:不。

    这是我第一次听说 eulerfx 提到的“读取模型模式”。这是一个很好的名字,但还有更多:

    “查询”部分背后的总体思路是查询数据的非规范化视图。在“读取模型模式”链接中,您会注意到用于填充读取模型的查询正在做一些提升。在上面提到的示例中,所需的数据操作并没有那么复杂,但是如果它确实变得更复杂了怎么办?这就是去规范化的用武之地。当您执行“命令”部分时,下一个操作是对数据进行去规范化并存储结果以便于阅读。所有繁重的工作都应该由您的域完成。

    这就是您询问消息传递的原因。这里有几种技术:

    • 同一个数据库、同一个表、不同列中的非规范化数据
    • 同一个数据库,不同表中的非规范化数据
    • 不同数据库中的非规范化数据

    那是存储。一致性如何?:

    • 立即一致
    • 最终一致

    最简单的解决方案(快速获胜)是对域中的数据进行非规范化处理,然后在通过存储库保存域对象后,立即将非规范化数据保存到相同的数据存储、相同的表、不同的列中。 100% 一致,您可以立即开始读取非规范化数据。

    如果您真的想要,您可以创建一组单独的对象来传输该数据,但编写一个简单的查询层来返回一些数据访问提供的数据承载对象会更简单框架(如果是.Net,则为DataRow/DataTable)。绝对没有理由变得花哨。总会有例外,但您可以继续编写数据容器。

    为了最终的一致性,您将需要某种形式的排队和相关处理。您可以推出自己的解决方案,也可以选择服务总线。这取决于您和您的时间/技术限制:)

    顺便说一句:我这里有一个免费的开源服务总线:

    欢迎任何反馈。但是任何旧的服务总线都可以(MassTransit / NServiceBus / etc.)。

    希望对您有所帮助。

    【讨论】:

    • 完整的答案。有趣的项目(Shuttle)——我正在研究它。
    • 如果我对非规范化数据使用不同的表(您的第二个选项),我是否可以说域持久性和非规范化数据将在同一个事务中?
    • @JD:这取决于您需要数据的一致性。如果绝对有必要让它 100% 一致(例如,可能是账户余额),那么可以;如果您的查询数据可能会过时一段时间,那么您不需要使用相同的事务。
    猜你喜欢
    • 1970-01-01
    • 2016-11-26
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多