Trello如何在没有原子事务的情况下存储MongoDB中其他文档(板卡,卡片)更新生成的操作?

问题描述 投票:0回答:1

我正在开发一个单页Web应用程序,它将使用NoSQL文档数据库(如MongoDB),我想在我对我的实体进行更改时生成事件。

由于大多数这些数据库仅支持文档级别的事务(MongoDB刚刚添加了ASIC支持),因此没有好的方法可以将更改存储在一个文档中,然后将这些更改中的事件存储到其他文档中。

比方说,我有一个集合'Events'和一个像Trello那样的'Cards'集合。当我从'Cards'集合中更改卡片的描述时,应该生成一个事件'CardDescriptionChanged'。

问题是,如果将更改保存到'Cards'集合并在'Events'集合中添加事件之间发生崩溃或出现错误,则此事件将不会保留,我不希望这样。

我已就此问题做过一些研究,大多数人会建议可以使用以下几种方法之一:

  1. 不要使用MongoDB,而是使用SQL数据库(我不希望这样)
  2. 使用事件采购。 (这引入了复杂性,我希望在某些时候清除旧事件,所以我不想保存所有事件。我现在可以使用快照并从快照点删除旧事件,但这有一个复杂性解)
  3. 因为这种性质的错误可能不会经常发生,所以只要忽略它们就有可能发生无法保存的事件(我也不想这样做)
  4. 使用事件/命令/动作处理器。存储命令/操作,如“ChangeCardDescription”,并使用将处理它们并更新实体的处理器。

我考虑过选项4,但有几个问题出现了:

  • 我如何管理并发?

我可以为同一个实体(如卡或板)排队所有命令,并确保它们按顺序处理,而不同实体(不同卡)的事件可以并行处理。然后我可以使用已处理的命令作为事件。这里的一个问题是对实体的改变可能生成可能不对应于单个命令的若干事件。我将不得不细分所有用户操作的细粒度命令,以便我可以将它们转换为事件。

  • 错误报告和错误处理。

如果此过程是异步的,我必须管理到客户端的错误报告。而且我还必须删除或标记失败的命令。

  • 我仍然有将标记命名为已处理的问题,因为没有事务。我知道我必须处理命令幂等以解决这个问题。

由于Trello使用MongoDB并生成动作('DeleteCardAction','CreateCardAction')并更改实体(卡片,板......),我想知道他们是如何解决这个问题的?

mongodb event-sourcing trello
1个回答
1
投票

创建一个名为FutureUpdates的新集合。使用单个文档将计划更新写入FutureUpdates集合,该文档定义您计划对卡片所做的更改以及您计划生成的事件。这个插入是原子的。

现在拿一张[ChangeStream][1]FutureUpdates系列,这将为您提供所需的更新流。从更改流中获取每个文档并应用更新。最后,更新FutureUpdates中的doc以将其标记为完成。此更新将再次是原子的。

将更新应用于事件和卡时,请确保包含用于在FutureUpdates中创建更新的文档的objectID。

现在,如果在FutureUpdates中插入更新后程序崩溃,您可以检查事件和卡集合是否存在包含更新的objectID的记录。如果它们不存在,那么您可以重新应用缺少的更新。

如果已应用更新但FutureUpdate doc未标记为完成,我们可以在恢复期间更新该更新以完成此过程。

实际上,您可以不断以原子方式更新FutureUpdates中每个更改的文档以跟踪进度。更新完成后,您可以归档旧文档或只删除它们。

© www.soinside.com 2019 - 2024. All rights reserved.