事件溯源投影模式:重复数据删除策略 - domaincentric


在典型的CQRS / ES系统中,由投射处理的事件具有至少一次交付保证。因此,通常需要实施重复数据删除以实现(感知)幂等性。

1. 基于事件ID
每个投射对应一个重复数据删除表
在单独的表中存储已处理的事件ID,并以事务方式读取当前余额,并仅在表中不存在事件ID时更新它。

CREATE TABLE handled_events (projection_id TEXT, event_id TEXT, UNIQUE(projection_id(36), event_id(36)));

每个投射的每个流的重复数据删除表:可以使用表来存储每个流的事件ID(而不是整个投射)。这将使查询和索引更有效:

CREATE TABLE handled_events (projection_id TEXT, stream_id TEXT, event_id TEXT, UNIQUE(projection_id(36), stream_id(36), event_id(36)));


2. 基于全局序列号
第二种方法依赖于一些事件存储为写入其中的所有事件提供全局排序的事实。如果您的事件存储确实为您提供了这样的序列号,那么它可以更好地替代使用显式事件ID。鉴于我们可以保证事件处理程序中的有序处理并且序列号严格增加,那么只有当存储的序列号小于事件接收的数量时,我们才会处理事件。

3. 基于流版本号
上一节中描述的解决方案依赖于事件存储将提供全局排序的事实。在大多数情况下,这应该不是问题,但有时选择db后端或缩放可能会迫使您放弃此约束。
如果使用基于stream_version的乐观锁实现事件存储,我们可以使用stream_version作为使用全局序列号的替代方法。

具体点击原文查看详细。