在cqrs中投影期间处理数据库故障

时间:2019-02-22 14:53:23

标签: cqrs event-driven-design

我们正在使用CQRS创建系统。我们的预测在mongodb中。我们正面临一些案件。我们有一个事件说OrderCreated。我们需要产生一个顺序order_no,例如#3,#4等。我们可以使用投影并将序列保留在表中,然后称为upsert方法。并获得一个新号码。发布一个新命令:GenerateOrderNumber。现在此帖子接受的硬件故障发生之前。如果重试,我们将有另一个号码。不好如何在cqrs中解决这种用例。

2 个答案:

答案 0 :(得分:2)

  

我们的预测在mongodb中<...>
  现在此帖子接受的硬件故障发生之前

所描述的问题很可能与CQRS或EventSoucring本身无关,而与投影存储(上面讨论的MongoDB)有关。

您正在尝试执行没有交易保证的潜在原子操作。由于硬件故障可能是在随机时间内造成的,因此数据库应具有在当前事务中回滚失败的原子操作的功能。

最好的选择是本机MongoDB事务,该事务自4.0版本-https://docs.mongodb.com/manual/core/transactions/开始可用-您的代码将如下所示:

session.startTransaction( … );
try {
  const lastNo = await eventsCollection.findOne( ... )
  await eventsCollection.insertOne( …, lastNo +1 )
  session.commitTransaction()
} catch (error) {
  session.abortTransaction()
}

如果必须使用旧版MongoDB,则仍可以使用事务。但是,您应该手动编写事务日志,而不是使用固有运算符,并在重新连接到数据库后执行监视已损坏的事务,并通过日志手动还原它们。

答案 1 :(得分:1)

您应该通过事件执行所有操作,甚至生成序列号。 对于您的情况,我建议您使用saga:

  • 构建用于生成order_no的投影
  • 触发新事件OrderCreated(此后,您将获得具有某些唯一ID的Order Aggregate)
  • 佐贺,收听此事件,触发事件GenerateOrderNo(从投影中获取下一个免费电话)

在这种情况下,您每次在失败后要求输入新的order_no都是一样的。

如果我理解您有误,请纠正我。