【问题标题】:CQRS Data store approach Nosql Or Sql ServerCQRS 数据存储方式 Nosql 或 Sql Server
【发布时间】:2014-09-18 10:11:42
【问题描述】:

我正在经历一个新项目的研究阶段,目前我正在与一位同事就项目的架构进行辩论。

我们已经同意,我们将使用 CQRS 和带有 azure 的事件溯源来创建分布式消息传递系统。它将是一个前端使用 Angular js 的 SPA,后端将是 Web API。

我们现在已经讨论了如何设置数据库,这就是差异所在。

我们已经同意将数据库拆分为两个数据库,一个用于读取和写入。 我的同事想将 sql server 用于读取和写入数据库,因为他的整个职业生涯都是在 sql 中度过的,除了 sql 什么都不想听到。 另一方面,我一直在研究NoSql,我觉得它更适合读取数据库,因为它的性能更好。

由于 CQRS 是关于最终一致性的,我已经读到 NoSql 数据库也基于此,这让我现在考虑使用 NoSql 来写入数据库。

我们还计划为每个聚合根创建一个事件表,而不是一个包含所有事件的通用事件表。 由于这些表不是关系表,这让我想到了为什么我们应该使用 sql server。

我的问题更多是关于人们如何创建他们的活动商店的最佳实践或一般方法。

  1. 您是对所有事件使用一个表还是为每个聚合根创建一个事件表?
  2. 将 NoSql 数据库用于 CQRS 应用程序的写入和读取数据库有哪些优点/缺点?
  3. 最后但并非最不重要的一点是,您将如何说服已与 Sql 结婚的固执工作同事转换为 NoSql 方法?

【问题讨论】:

    标签: nosql cqrs event-sourcing


    【解决方案1】:

    注意:我的回答是从 2014 年开始的。时代变了,现在有几个 NoSQL 数据库支持多文档事务。我仍然提倡 PostgreSQL 存储事件,特别是因为它对 JSON 的支持非常棒。


    最后一个问题主要是基于意见,所以让我从我的角度回答前两个问题。

    在此之前,让我先说一下我们的事件存储正在使用 SQL 服务器 (Postgres)。使用 CQRS+ES,拥有一个主要的 master 来写入数据库是微不足道的,让存储库从 slave 读取(不要与 CQRS 读取混淆)。在这个设置中,可扩展性应该不是问题(如果 Reddit 可以在主/从中 scale with Postgres,那么你也可以)。

    我对 NoSQL 存储的各种选项进行了广泛的评估。归根结底,对于 CQRS+ES 设置,我找不到任何优于主/从模式下的 SQL 方法的优势,IMO 将超过 NoSQL 数据库的劣势。

    特别是,在 SQL 存储中实现乐观锁定(streamId 和版本字段的唯一约束)是微不足道的,但在简单的 NoSQL 键值存储中实现可靠的乐观锁定却非常困难(不可能?)。

    使用一些文档存储是可能的(我认为NEventStore 仅支持 RavenDB 和 MongoDB 是有原因的。):

    1. RavenDB 支持 ACID 事务,但您必须使用/部署 .NET,这对某些人(包括我们)来说不是一个选项。
    2. MongoDB 具有您需要的服务器端原子操作 将事件附加到事件流并改变版本 原子操作中的数字,但存在一些技术限制(特别是 最大文档大小)让我远离 MongoDB 作为 活动商店。另外,我在 InfoQ 上阅读了 this article 关于 分区容差,而 Postgres 似乎要多得多 比 MongoDB 更可靠

    在 Postgres 中,我对所有事件使用一个事件表。

    至于第二个问题,我认为你必须区分事件存储和读取模型。我们将 SQL 服务器用于事件存储(出于上述原因),但对于 CQRS 读取模型,我认为 NoSQL“数据库”非常适合,因为最终一致性方法非常适合使用 NoSQL 范式。此外,通常只能通过键查询读取,因此您可以使用任何您喜欢并满足您需求的键值存储。我们甚至根本没有使用数据库,而是根据需要重新构建的内存网格。

    【讨论】:

    【解决方案2】:

    就个人而言,我更喜欢每个表一个聚合,但这取决于具体情况。即使对所有聚合使用一张表,也可以使用分区技术来缓解潜在的性能问题。

    我认为NoSQL对于读写来说都是可行的,但是SQL数据库确实提供了一个实用的特性:事务性。当您需要在一个事务中提交多个事件时,这尤其有用。对于 NoSQL 数据库,您可能必须更改架构才能实现此目的。例如,在采用 Mongo 时使用每个文档的每个事务。或者您可以使用 Cassandra 并将每一行作为一个聚合(每列一个事件,Cassandra 为行级别提供部分事务性)。

    但是,如果您的程序每个事务只发布一个事件,或者一致性不是一个强要求,这并不是一个很大的优势。

    【讨论】:

      【解决方案3】:

      仅仅因为您没有使用 FK(关系),这使得 SQL 成为事件溯源的“矫枉过正”。 FK 在 SQL 中不是强制性的。

      NoSQL 是一个很酷的概念,但根据我的个人经验,我发现使用 SQL 在各个方面都更容易。

      不要想太多。使用 SQL。让你的同事一个人呆着 :) (开玩笑)并完成工作。归根结底,我们大部分的“头痛”是我们无法阻止新技术/经验的诱惑。

      有意义吗?

      【讨论】:

      • 上次我想到这一点时,同事们对 SQL 有很大的问题,如果你很小并且没有生成大量事件,我必须使用 bcp 来解决。事件 = 插入性能而不是 SQL 的强项。跨度>
      • 我开始相信用于事件存储的 SQL DB 是先决条件,因为您必须使用表示该状态更改的 MOM 事件消息(在发件箱中)以原子方式持久化应用程序状态更改(在偶数存储中)。如果您今天不使用消息传递,则可以稍后使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-18
      相关资源
      最近更新 更多