CQRS数据存储方法Nosql或Sql Server

use*_*251 12 nosql cqrs event-sourcing event-store

我正在进行一个新项目的研究阶段,目前我正与一位工作同事就该项目的架构进行辩论.

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

我们现在讨论了如何设置数据库,这就是发生差异的地方.

我们同意将数据库拆分为两个数据库,一个用于读写.我的同事想要将sql server用于读写数据库,因为他在sql中度过了他的整个职业生涯并且除了sql之外不想听到任何其他内容.另一方面,我一直在研究NoSql,我觉得它适合读取数据库,因为它更适合性能.

由于CQRS完全是关于最终的一致性,我已经读过NoSql数据库也基于此,现在让我考虑将NoSql用于写入数据库.

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

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

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

Ale*_*ger 11

注意:我的答案来自2014年.时代已经发生变化,现在有几个NoSQL数据库支持多文档事务.我仍然提倡使用PostgreSQL来存储事件,因为它有很棒的JSON支持.


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

在此之前,让我说我们正在为我们的事件存储使用SQL服务器(Postgres).使用CQRS + ES,只需要一个主数据库来写入数据库,从存储库中读取存储库(不要与CQRS读取混淆).在这种设置中,可扩展性应该不是问题(如果Reddit可以在主/ 从中与Postgres一起扩展,那么你也可以).

我已经对NoSQL商店的各种选项进行了广泛的评估.在一天结束时,对于CQR​​S + ES设置,我发现在主/从模式下的SQL方法没有任何优势,IMO将超过使用NoSQL数据库所带来的缺点.

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

对于一些文档存储,它是可能的(我认为有一个原因,为什么NEventStore只支持RavenDB和MongoDB.):

  1. RavenDB支持与ACID的事务,但你必须使用/ deploy .NET,这对某些人来说不是一个选择(包括我们).
  2. MongoDB具有服务器端原子操作,您需要将事件附加到事件流并在原子操作中碰撞版本号,但是有一些技术限制(特别是最大文档大小)让我远离MongoDB一个活动商店.另外,我在InfoQ上阅读了有关分区容错的文章,Postgres似乎比MongoDB 更 可靠.

在Postgres中,我正在为所有事件使用一个事件表.

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


Yug*_*hou 5

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

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

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