在 cqrs 投影期间处理数据库故障
Handling DB Failure during projection in cqrs
我们正在使用 CQRS 创建系统。我们的预测在 mongodb。我们面临一些情况。我们有一个事件说 OrderCreated。我们需要生成一个顺序 order_no,例如 #3、#4 等。我们可以使用投影并在 table 中保留一个序列,然后调用 upsert 方法。并获得一个新号码。 Post 一个新命令:GenerateOrderNumber。现在在此之前 post 接受硬件故障发生。如果我们重试,我们将有另一个号码。这不好。如何在 cqrs 中解决此类用例。
您应该通过事件执行所有操作,甚至生成序列号。
在你的情况下,我建议你使用 saga:
- 构建用于生成 order_no
的投影
- 触发新事件 OrderCreated(此后您将拥有带有一些唯一 ID 的订单聚合)
- saga,侦听此事件,触发事件 GenerateOrderNo(从投影中获取下一个免费号码)
在那种情况下,任何时候你在失败后询问新的 order_no 都是一样的。
如果我理解有误,请指正。
Our projections are in mongodb <...>
now before this post accepted hardware failure occur
很可能所描述的问题与 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 版本,仍然可以使用交易。但是不要使用内部运算符,您应该手动写入事务日志,并在重新连接到数据库后对损坏的事务执行监视并通过日志手动恢复它们。
我们正在使用 CQRS 创建系统。我们的预测在 mongodb。我们面临一些情况。我们有一个事件说 OrderCreated。我们需要生成一个顺序 order_no,例如 #3、#4 等。我们可以使用投影并在 table 中保留一个序列,然后调用 upsert 方法。并获得一个新号码。 Post 一个新命令:GenerateOrderNumber。现在在此之前 post 接受硬件故障发生。如果我们重试,我们将有另一个号码。这不好。如何在 cqrs 中解决此类用例。
您应该通过事件执行所有操作,甚至生成序列号。 在你的情况下,我建议你使用 saga:
- 构建用于生成 order_no 的投影
- 触发新事件 OrderCreated(此后您将拥有带有一些唯一 ID 的订单聚合)
- saga,侦听此事件,触发事件 GenerateOrderNo(从投影中获取下一个免费号码)
在那种情况下,任何时候你在失败后询问新的 order_no 都是一样的。
如果我理解有误,请指正。
Our projections are in mongodb <...>
now before this post accepted hardware failure occur
很可能所描述的问题与 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 版本,仍然可以使用交易。但是不要使用内部运算符,您应该手动写入事务日志,并在重新连接到数据库后对损坏的事务执行监视并通过日志手动恢复它们。