5

Here是一篇很好的文章,它描述了什么是ES以及如何处理它。EventSourcing竞赛条件

那里一切都很好,但有一个图像困扰着我。这是

ES example

据我所知,在分布式事件为基础的系统,我们能只能达到最终一致性。无论如何......我们如何确保我们不会预订更多座位?如果有很多并发请求,这尤其是一个问题。

可能发生n个聚合填充相同数量的保留席位,并且所有这些聚合实例都允许预留。

+0

这只是简单的乐观锁定... – plalx

回答

2

将会有几种方法来处理这种情况。

首先,事件流将使当前版本成为添加的最后一个事件的版本。这意味着,如果事件流在加载时不在版本中,那么当您不应或不应该能够保留事件流时。由于第一次写入会导致事件流的版本增加,所以第二次写入将不被允许。由于事件本身并不是排放的,而是事件采购的结果,因此我们在您的示例中不会出现竞争条件类型。

那么,如果您的命令在队列后面处理,则应该重试任何失败。如果无法处理请求,您可以输入正常的“我很抱歉,戴夫,我害怕我不能这样做”的方案,让用户知道他们应该尝试别的。

另一个选择是通过针对某些表行发布更新来启动处理,以序列化对聚合的任何调用。可能不是最优雅的,但它确实会导致整个系统范围内的处理。

我想,在很大程度上,真的不可信当谈到事务处理时,信任读取存储。

希望帮助:)

0

据我所知,在分配基于事件的系统,我们能够既达到最终一致性,反正...如何不允许预订更多的席位比我们有?特别是在许多并发请求方面?

所有事件对于运行它们的命令是私有的,直到记录簿确认写入成功为止。所以我们根本不会分享这些事件,也不会在不知道我们版本的“接下来发生的事情”被记录簿接受的情况下向调用者报告。

事件的写入类似于聚合历史记录中尾指针的比较和交换。如果另一个命令在我们运行时改变了尾指针,我们的交换失败了,我们必须减轻/重试/失败。

在实践中,这通常是通过让写入命令写入记录的预定位置来实现的。 (例如:GES中的ES-ExpectedVersion)。

如果预期的位置在错误的地方,预计记录簿将拒绝写入。将该位置视为RDBMS中表格中的唯一键,并且您有正确的想法。

这意味着,有效,即写入到事件流是实际上一致的 - 记录的书只允许写,如果你写的位置是正确的,这意味着立场没有改变,因为您加载的历史记录的副本被写入。

命令通常直接从记录簿中读取事件流,而不是最终一致的读取模型。

虽然可能会发生n-AggregateRoots将被填充相同数量的保留位置,这意味着在保留方法中进行验证将无济于事。然后n-AggregateRoots将发出成功保留的事件。

每一个状态位都需要一个聚合根监督。你可以有n个不同的副本运行,所有的副本都会竞争写入相同的历史记录,但比较和交换操作只允许一个赢家,这确保了“该”聚合具有单个内部一致的历史记录。