【发布时间】:2019-09-04 15:30:34
【问题描述】:
我正在开发一个将使用 NoSQL 文档数据库(如 MongoDB)的单页 Web 应用程序,并且我想在对我的实体进行更改时生成事件。
由于这些数据库中的大多数仅支持文档级别的事务(MongoDB 刚刚添加了 ASIC 支持),因此没有好的方法可以将更改存储在一个文档中,然后将这些更改中的事件存储到其他文档。
例如,假设我有一个集合“事件”和一个集合“卡片”,就像 Trello 一样。当我对“卡片”集合中的卡片描述进行更改时,应该会生成一个事件“CardDescriptionChanged”。
问题是,如果在保存对“卡片”集合的更改和在“事件”集合中添加事件之间发生崩溃或一些错误,则此事件将不会持续存在,我不希望这样。
我已经对此问题进行了一些研究,大多数人会建议可以使用以下几种方法之一:
不要使用 MongoDB,而是使用 SQL 数据库(我不想那样)
使用事件溯源。 (这引入了复杂性,我想在某个时候清除旧事件,所以我不想保存所有事件。我现在可以使用快照并从快照点删除旧事件,但这有一个复杂性解决方案)
由于这种性质的错误可能不会经常发生,请忽略它们并冒着发生无法保存的事件的风险(我也不希望这样)
使用事件/命令/动作处理器。存储命令/动作,如“ChangeCardDescription”,并使用处理器来处理它们并更新实体。
我已经考虑过选项 4,但出现了几个问题:
- 如何管理并发?
我可以将同一实体(如卡片或棋盘)的所有命令排队,并确保它们按顺序处理,而不同实体(不同卡片)的事件可以并行处理。然后我可以将处理后的命令用作事件。这里的一个问题是对实体的更改可能会生成多个事件,这些事件可能不对应于单个命令。我必须将所有用户操作分解为非常细粒度的命令,以便我可以将它们转换为事件。
- 错误报告和错误处理。
如果此过程是异步的,我必须管理向客户端报告错误。而且我还必须删除或标记失败的命令。
- 我仍然无法将命令标记为已处理,因为没有事务。我知道我必须使命令处理具有幂等性才能解决此问题。
由于 Trello 使用 MongoDB 并生成操作('DeleteCardAction'、'CreateCardAction')并更改实体(卡片、板..),我想知道他们如何解决这个问题?
【问题讨论】:
标签: mongodb event-sourcing trello