0

当使用事件溯源和聚合作为事务范围时,您显然更喜欢在单台机器上拥有聚合。但是,如果您还想构建一个高可用性和水平可扩展的系统,您还希望在不同数据库上的许多机器上复制这种状态。

如果在任何给定时刻只允许该网络中的一台机器上的一个写入端,则其他机器最终可以是一致的读取端。但是为了最大限度地提高写入性能,我想同时允许多个写入端会更好。但是在这样的系统中如何处理一致性和共识呢?

当两台或多台机器想要同时更新共同但复制的状态时,我如何确保命令由所有写入端以相同的顺序处理,以便生成的事件相同并且具有相同的顺序?Lamport 时钟是解决方案的一部分吗?

4

2 回答 2

0

但是为了最大限度地提高写入性能,我想同时允许多个写入端会更好。但是在这样的系统中如何处理一致性和共识呢?

在事件源系统中,写入端的一致性总是很强。这是由聚合和 Event store使用乐观锁定强制执行的:在并发写入的情况下(实际上事件仅附加到 store),将重试hole 命令。这是可能的,因为聚合命令方法是纯(无副作用)方法。只要事件没有持久化,就可以重试该命令。

当两台或多台机器同时更新状态时(选择哪一台并持久化?)

两个都。第一个(总是有第一个)命令生成持久保存到存储的事件。由于低级并发异常,secons 命令失败。然后通过加载+应用所有先前的事件重试,包括由第一个命令生成的事件。然后,如果新状态不允许处理第二个命令,则第二个命令会生成其他事件,这些事件也会被持久化或抛出异常。

您必须注意到第二个命令至少执行了两次,但每次之前的事件(因此状态)都不同。

基础设施保留一个附加到每个聚合流的聚合版本。每个事件追加增加这个版本。聚合 id 和版本有唯一约束。这可能是所有事件存储的实现方式。

当机器行为不端(不知不觉或有意)并将错误事件传播到网络的其余部分时(如何检测到这一点?)

我看不出这是怎么发生的,但如果它发生了,那真的取决于你对错误事件的理解。你可以有一些 Sagas/Process 管理器来分析事件并触发一些发送给某种主管的电子邮件。

于 2017-04-11T19:23:54.060 回答
0

我在我的 Shuttle.Recall(无耻插件)ES 实现中处理这个问题的方式是在聚合 id事件存储中的版本上构建一个唯一的聚集索引。这样,同一 AR 上的多个写入永远不会重叠,并且两者中的一个将“丢失”。当然,这只能使用中央数据存储来工作,但您的实现可能有类似的机制可用。

对于可以同时写入事件存储的客户端数量没有限制。但是,投影处理必须是单个机器上每个命名投影的单个线程,因为事件排序非常敏感。好吧,我猜可以在不同的机器上处理不同的投影。

于 2017-04-12T11:12:04.523 回答