首页 > 解决方案 > 使用 Axon 对业务领域的复合唯一约束

问题描述

我们在系统中利用 AxonIQ 框架。我们在实现基于聚合业务字段的复合 uniq 约束时遇到了问题。

考虑以下聚合:

@Aggregate
public class PersonnelCardAggregate {

    @AggregateIdentifier
    private UUID personnelCardId;

    private String personnelNumber;

    private Boolean archived;

}

我们希望避免在未归档(归档 == 假)记录的范围内出现人员编号重复。同时存档记录范围内可能存在人员编号重复。

查询端检查似乎不是一种选择。考虑到我们系统的最终一致性特性,可能同时存在多个具有相同personalNumber的创建请求,查询端可能落后。

解决方案是什么?

标签: cqrsaxoneventual-consistency

解决方案


您要问的是,一旦您开始按照 CQRS 范式和 DDD 建模技术实现应用程序,就会出现一个问题。

PersonnelCardAggregate您的场景中,维护单个“人事卡”的一致性边界。但是,您希望扩展此范围以在系统中的所有人员卡中实现唯一性约束。

我觉得这个博客很好地解释了你遇到的“基于集合的一致性验证”的问题。我不会重复他的整个博客,但他总结为有四个选项来解决问题:

  1. 为您的人事卡引入锁定、事务和数据库约束
  2. 在发出命令之前使用混合锁定字段
  3. 真正在最终一致的查询模型上
  4. 重新审视领域模型

公平地说,如果您使用事件驱动方法来更新您的命令和查询模型,选项 1 将不起作用。您在原始问题中已将选项 3 推回。

鉴于我不是领域专家,我无法为您推断选项 4,但我猜测它PersonnelCardAggregate不属于更大的封装聚合根。也许您所说的业务约束,因此personalNumbers可以删除或调整重用选项?就像我说的那样,我不能说这是对你的事实答案,因为我不是领域专家。

剩下的选项 2,在我看来也是最务实的方法。我觉得这需要在您的命令调度端组合缓存来处理快速连续的命令,以解决最终的一致性问题。为了捕捉更新仍然意外发生的情况,我将介绍某种形式的事件处理程序,它 (1) 从personalNumber/archived的角度了解整套“PersonnelCards”,并且 (2) 可以对错误的介绍做出反应发送补偿动作。

因此,您将在应用程序的事件处理端引入一些业务逻辑,我强烈建议将其与更新查询模型的应用程序部分分开(因为用例完全不同)。

总而言之,这是一个困难的话题,有几种方法可以解决它。顺便说一下,这不是 Axon 特定的问题,而是更多通过 DDD 和 CQRS 对应用程序建模的情况。


推荐阅读