我拥有一个使用 Neo4j 作为图形数据库的应用程序。
我将读取和写入分开(遵循 CQRS 建议),以便实现命令模式并优化我的请求(页面请求),整个共享同一个数据库:neo4j 数据库。(不是两个不同的)
现在,我计划存储一些领域事件,例如UserRegisteredEvent
等,以便由 Actors (Akka) 中托管的一些事件处理程序出队。
将域事件存储在共享数据库中(在我的例子中作为简单的 Neo4j 节点)是否有意义?
或者我真的需要一个三级数据库,例如MySQL?
我明确指出,我的解决方案不需要事件溯源。
我正在尝试使用 spring-data-jpa 实现简单的 cqrs 应用程序,所以我有 2 个用于编写的表 - 例如人和汽车(一个人可以拥有汽车列表)。我还使用创建为 select * from person join car 的一个视图...
因此示例查询可以给出输出(一个用户有 2 辆车)
firstName|lastName| car_brand | car_model |
marek |k | tesla | s |
marek |k | mercdes | 190 |
Run Code Online (Sandbox Code Playgroud)
现在我正在尝试在 jpa 中映射此视图,并且正在尝试嵌入列表
@Embeddable
class CarSnapshot {
private String carBrand;
private String carModel;
}
Run Code Online (Sandbox Code Playgroud)
和
class PersonSnapshot {
private String firstName;
@Embedded // I tried also @OneToMany and ElementCollection
private Set<CarSnapshot> cars;
}
Run Code Online (Sandbox Code Playgroud)
但它不适用于我的情况。你知道如何修复它吗?而且一对一映射(一个人最多拥有一辆车)效果非常酷
关于存储库模式的一些事情困扰着我
存储库的实际用途是什么?我将其理解为 Domain.Model 的一部分,它提供了在聚合上执行命令的方法,仅此而已。
现在,如果您使用提供 CUD 方法的通用基础存储库,您可能会说您的域不是通用的,因此存储库不是通用的,我同意,但只是从一个角度来看,发出的是查询,而不是命令。
我认为通用存储库至少在 DDD 与 CQRS 混合的背景下消除了对 Domain.Repositories 的需求(我知道我可能听起来有争议,这也正是我的看法)。但是,如果您将命令与查询分开,那么您将拥有仅包含 CUD 操作的 WriteRepositories。因此到处都有很多重复的东西。
想象一下这个
CustomerRepository : ICustomerRepository
{
void Add(CustomerAggregate agg);
void Update(CustomerAggregate agg);
}
BookRepository : IBookRepository
{
void Add(BookAggregate agg);
}
SubscriptionsRepository : ISubscriptionsRepository
{
void Add(SubscriptionAggregate agg);
void Update(SubscriptionAggregate agg);
void Delete(SubscriptionAggregate agg);
}
Run Code Online (Sandbox Code Playgroud)
……另外 5 个仓库
那么,在使用 Command.Stack + Query.Stack 的 CQRS 模式的 DDD 上下文中,通用存储库是否有意义?如果是这样,它是否消除了对 Domain.Repositories(命令存储库)的需要?
domain-driven-design repository ddd-repositories repository-pattern cqrs
在开始开发 CMS、CRM 或 ERP 之前,我正在寻找架构选择复杂性的一些线索。
我能够找到这个类似的问题:A CRM Architecture (open source app) 但它似乎足够老了。
我最近观看和阅读了一些会议,讨论了整体式与分布式、DDD 哲学、CQRS 和事件驱动设计等。在考虑到每个架构的缺陷(我认为)后,我对架构选择比以前更加恐慌。
我发现不幸的是,在网上可以轻松找到的所有微服务和分布式系统的示例中,它们总是以电子商务为例(客户、订单、产品......)。对于此类示例,存在多个数据库(通常是微服务的 NoSQL DB)。我看到了(或多或少)==> 为每个上下文保留必要数据的简约表示的优点。
但如何寻找一个独特的关系数据库呢?我真的认为我需要一个单一的关系数据库,在一家生产 CRM 的公司工作过(无法访问机器的源代码,但访问数据库的结构),我可以看到关系的重要性:对于列表、报告来说是必要的,并查阅 CRM 内实体之间的链接(一个联系人可以有多个公司,相反,每个用户有多个操作、任务,但他的每个任务也可以分配给其他用户,甚至链接到其他项目,例如:“联系人”、“公司”、“出版物”、“日历日期”等。而且每个表中可以有很多记录(+100,000行),所以索引的选择会相当重要,交易是全方位的-present 因为会有大量的并发访问数据记录)。
我对自己说的是,如果我选择使用微服务系统,将会有很多微服务要做,因为确实会有很多不同的上下文,并且很有可能拥有一堆不同的领域模型。然后我最终会有这样的印象:必须点亮花环的每个小灯泡,也许同时运行的进程太多。
为了尽量准确而不是全方位,我有两个问题要问:
先感谢您 !
(这将是.NET Core,草案在这里:https ://github.com/Jin-K/simple-cms )
我有一个简单的 DDD 服务,带有文章聚合根。我使用 MediatR 和 CQRS 来分离命令和查询。在 DDD 域中不应依赖于应用程序和基础设施层。我有一个存储库 IArticleRepository,用于从文章数据库中组合一些数据。我有一个休息端点,用于通过某种过滤器获取文章,以便我创建
ArticleQuery : IRequest<ArticleDto(or Article)>
Run Code Online (Sandbox Code Playgroud)
那么这个查询对象应该是什么时候呢?我每个聚合都有一个存储库,因此在域层中我有 IArticleRepository。我需要指定输入参数类型。如果我将查询放在基础设施或应用程序层中,我会获得从域指向基础设施或应用程序的依赖关系。如果我将查询放在域中,则会违反 DDD,因为查询与业务无关。如果我不将对象放入存储库,而仅将字段作为参数放入存储库,则会有大约 10-15 个参数 - 这是代码味道。
它需要,因为在查询处理程序中还出现搜索引擎逻辑,所以我决定通过存储库或类似的东西将来自基础设施中搜索引擎逻辑的 SQL 逻辑封装起来。
关于在 .NET API 中使用 CQRS 模式,我见过一些示例,其中请求直接反序列化为命令/查询,然后发送出去进行处理,如下所示:
[HttpPost]
public async Task<IActionResult> CreateOrder(CreateOrderCommand command)
{
var result = await _mediator.Send(command);
return Ok(result);
}
Run Code Online (Sandbox Code Playgroud)
在其他示例中,使用某种 dto 或请求对象,然后将其输入到命令/查询的构造函数中,如下所示:
[HttpPost]
public async Task<IActionResult> CreateOrder(CreateOrderDto model)
{
var command = new CreateOrderCommand(model.orderNumber, model.firstName...);
var result = await _mediator.Send(command);
return Ok(result);
}
Run Code Online (Sandbox Code Playgroud)
第一种方法对我来说看起来更有吸引力,因为它减少了模型和代码行。您是否有理由使用第二种方法并将请求对象与命令对象分开?
我有一个用于读取和写入操作的 SQL Server 数据库,并且我正在实现 CQRS 模式以实现代码隔离和可维护性,以便我可以将读取操作分配给团队中的少数资源,并将写入操作分配给其他资源,我认为使用 CQRS 似乎采取干净的方法。
现在,每当我的数据库中的表上发生插入/更新/删除时,我需要向需要了解我的系统中的更改的其他系统发送消息,因为我的数据库是主数据,因此这里发生的任何更改都需要投射到下游系统,以便他们获取最新数据并将其维护在自己的系统中。为此,我可以使用 MQ 或 Kafka,因此每当有变化时,我都可以生成关键消息并放入 MQ 中或使用 kafka 进行消息传递。
到目前为止,我还没有像我想象的那样使用事件源,因为我没有多个数据库用于读/写,所以我可能不需要事件源,我的假设是否正确,如果我们有单个数据库,我们就不需要事件源?或事件源可以在利用 MQ 或 Kafka 中发挥任何作用,我的意思是,如果我使用事件源模式,我可以首先将数据保存在主数据库中,然后使用事件源模式将更改写入 MQ 或使用 kafka 写入消息,我一无所知在这里,我们是否可以使用 MQ 或 Kafka 的事件源模式。
将消息写入 MQ 或使用 Kafka 是否需要事件源?或者在我的情况下根本不需要,因为我只有一个数据库,我不需要知道记录系统发生的一系列更新,我关心的是主数据库中记录的最终状态然后使用 MQ 或 Kafka 将更改发送到有 CRUD 操作的下游系统,以便下游系统获得最新的更改。
我正在学习分布式系统中的事件源和 CQRS,但在尝试确定何时是执行验证的最佳时间时遇到了一些麻烦……在事件存储之前还是之后?我已经对这个主题进行了大量的搜索和阅读,但我似乎找不到解决这个问题的答案/建议。
例如(简单的例子),如果我有一个 Web API 请求从银行帐户提取一些钱,我可能会执行以下验证:
当请求传入时,我是在执行上述验证之前保存事件(并且存在存储无效事件的风险)还是在验证之后保存事件(并且存在在过程中途出现问题的风险,例如服务出现故障,并且不存储事件根本)?对于 CQRS,事件是在执行命令之前存储还是作为命令的一部分(在命令处理程序中)存储?
我可以理解,在发出请求之前会执行一些验证(例如,提取的有效金额),但可能存在在发出请求之前无法完成某些验证的情况。
这也导致我要弄清楚如何在 Web API 调用的响应中返回错误(例如银行帐户无效)?
我对这个主题的理解可能都是错误的,但正如我之前提到的,我刚刚学习这个主题,我希望有人有答案,或者可以给我指出一些帖子/文章,这将有助于我的理解。
我决定在Greg Young实施的例子中熟悉具体的CQRS 实施
我不明白的是这里服务的含义是什么,因为它似乎完全不同于我们常用的三层模式.
客户端更改收到的DTO并创建一个命令,该命令由其处理程序处理,该处理程序调用域对象的方法.
然后创建事件并将其存储在事件存储库中并发布以同步去除denormolized部分.
我找不到这个链中的服务.
我的同事告诉我,举例来说,如果我们不希望大数据存储为一个域的一部分,当我们存储在报道,但是当我们需要它在我们的领域,我们发布其返回从服务的东西的事件.
但我无法在脑海中清晰地形成这幅画面.
任何人都可以解释这里应该做什么服务?
我正在尝试学习EventStore,我喜欢这个概念,但是当我尝试在实践中应用时,我会陷入同样的困境.我们来看看代码:
foreach (var k in stream.CommittedEvents)
{
//handling events
}
Run Code Online (Sandbox Code Playgroud)
两个问题:
当应用程序在某些维护后启动时,我们如何以安全的方式书签哪些事件开始读取?有使用的模式吗?
一旦事件全部被消耗,循环结束......消息到达运行时间怎么样?我希望呼叫阻塞,直到一些新消息到达(当然需要在一个线程中处理)或者有类似BeginRead EndRead的东西.
我是否必须绑定ESB来处理运行时事件,或者EventSore是否提供了一些工具来执行此操作?
我试图用一个例子更好地解释 假设聚合是一个金融投资组合,而应用程序是一个向交易者展示该投资组合的应用程序.假设交易者连接到Web应用程序,他会查看自己的投资组合.当前状态将是整个历史记录,因此我必须阅读大量记录以重现状态.我想这可以通过一个所谓的快照完成,但是谁负责创建它?什么时候应该选择创建聚合?怎么能猜出聚合的快照存在?对于运行时部分:一旦用户查看重建的投资组合状态,实时部分就开始运行.用户可以通过在市场中成功执行该订单来下订单并创建新的头寸.基础设施如何更新投资组合?我希望,但也许我完全错了,让相同的事件流成为新事件新长位置的来源,否则我有两条路径处理同一聚合的状态.我想知道这是策略应该如何工作,即使我觉得有两个州代理有点棘手,可能会重叠.只是为了澄清我如何担心重叠:
我在流媒体事件之前订阅了一个事件总线,以更新投资组合的状态.总线上出现了一些"开仓事件":我必须处理它们,但是由于尚未实现,投资组合可能处于正确状态.即使我能够处理这样的事件,我会在阅读流时再次找到它们.
更阴险:我打开流,我读了所有事件,我创建了一个状态.然后我订阅了总线:总线上的一些消息发生在steram读取结束和订阅开始之间的中间:这些事件丢失且聚合未处于正确状态.
请耐心等待,我的英语很差,争论很棘手,希望我设法分享我的疑问:)
cqrs ×10
.net-core ×2
c# ×2
repository ×2
.net ×1
apache-kafka ×1
api ×1
architecture ×1
crm ×1
event-store ×1
jpa ×1
mediatr ×1
neo4j ×1
rabbitmq ×1
sql-server ×1