首页 文章

使用CQRS和事件源时的唯一性验证

提问于
浏览
18

我正在尝试使用Event Sourcing实现我自己的CQRS基础架构,以便更好地学习它 . 作为一个示例项目,我正在实现一个博客引擎,我知道它可能不是一个完美的契合,但我只想做一些真实的事情 .

我现在遇到的问题是验证 . 每个帖子都有 shortUrlshortUrl 应该是唯一的,但我应该在哪里将此验证放在域中?我知道在我通过读取读取存储来发送命令之前我将进行验证,以便在创建create post命令或更新post命令时检查它是否有效 .

我可以想到两个“解决方案” .

  • 有一个 Blog 聚合,可以跟踪所有与博客相关的设置以及对所有帖子的引用 . 但在我看来,这个问题是我必须在那个场景中处理聚合之间的通信以及每次我需要验证 shortUrl 的唯一性时我需要从事件存储中读取所有事件来创建所有帖子这似乎很复杂 .

  • 我有的第二个选择是当事件被触发时,我创建读取模型的事件处理程序会在发现它有两个指向不同帖子的短网址时触发重复的短网址事件 . 读取模型在检测到错误时触发事件是否有效?

还有其他选择吗?请注意,我知道我的域名可能不适合cqrs和DDD,但我这样做是为了在小域中学习 .

3 回答

  • 1

    我会选择一个域名服务,负责生成独特的ShortURL . 您可以使用事务DB来实现此行为 . 通常,此服务将由BlogPost聚合的命令处理部分使用 . 如果存在重复的ShortURL,则可以触发DuplicateUrlErrorEvent . 您可以通过使用相同的数据源创建精简查询模型来预先在UI中捕获此内容(但绝不是100%),这样您就可以在提交帖子之前查询缩短的URL是否唯一(如@ RyanR的回答所述) ) .

  • 0

    这取决于“企业”想要发生什么 . 如果您希望客户端(命令的创建者)负责选择一个短URL,它应该有一个读取存储,它可以验证它的唯一性 . 当用户键入短URL时,视图应检查短URL是否唯一,如果不是,则显示验证错误 . 每当保存帖子时,事件将发布更新的信息(包括短URL),以使读取存储保持同步 .

  • 0

    我已经阅读了关于这个和相关问题的各种答案 .

    决定归结为正确性 . 如果您可以宽恕并接受某种程度的操作的不完美行为,那么您的问题就更容易解决,特别是在弱一致性保证下 .

    但是,如果您需要一致性,则应使用具有强一致性保证的持久性服务 .

    例如,创建短URL的命令将验证读取存储不包含这样的短URL,如果我们可以首先将更改提交到读取存储,我们将只提交事件 .

    如果我们可以将更改提交到读取存储,则我们没有违反任何唯一性约束(假设您的读取存储实施了这样的约束),然后我们就可以继续了 .

    但是,由于我们有两个事务不一定在同一个数据库上,所以在第一次提交后我们可能会失败 . 这没关系,因为整个操作也会失败 . 读存储将在一段时间内反映出不一致的状态,但只要我们修复聚合,读存储就会以一致的状态返回 .

    作为维护程序,我们可以定期修复可能存在错误的聚合 . 您可以通过引入错误标志来实现此目的,只有在两个事务成功提交时才会清除该标志 .

    有一个例子,银行允许用户透支他们的帐户,因为他们有附加费用来补偿 . 这引发了一些问题,因为解决这样的问题似乎很草率,甚至是懒惰 . 有人称之为聪明 . 我不知道该怎么想 . 银行可能有足够的资金来支付它,所以他们不妨忽视它,但这不是世界目前的运作方式 . 无论如何,我离题了 .

    从正确的立场来看,我们的阅读商店具有强大的一致性保证,我们会以这样的方式编写我们的预测如果余额为负数,则无法将事务提交到读取存储 . 因此,可能发生的最糟糕的事情是从读取存储中扣除费用,但操作从未在事件存储中完全提交 . 在维护程序发现错误标志并修复帐户之前,用户将看到其帐户中缺少资金 . 我认为这是一个妥协的工作 .

相关问题