【问题标题】:Best way to enforce invariants between aggregates?在聚合之间强制执行不变量的最佳方法?
【发布时间】:2017-11-08 13:04:43
【问题描述】:

处理聚合之间的一致性的最佳方法是什么?有一个 Vaugn Vernon 书中的例子,你有 BacklogItem 聚合和 SprintAggregate。当 BacklogItemEvent 被引发时,事件处理程序会捕获它并尝试更新 Sprint Aggregate。如果此操作失败怎么办?如何找到处理这种情况的最佳方法?据我了解有3个选项: 1) 在一个事务中更新所有聚合。我们失去了可扩展性,但我们获得了一致性。 2)什么都不做。只需记录和错误并等待人工干预。 3)使用传奇。这使设计复杂化并迫使我们实现每个用例,这些用例必须在单独的对象(saga)中的聚合之间强制执行变体。如果 Sprint 更新失败,saga 将尝试 Uncommit Backlog 项目(补偿)。 您会选择哪个选项,您的标准是什么?

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

    处理聚合之间的一致性的最佳方法是什么?

    如果您的聚合设计正确,那么您可以处理聚合之间随时间推移的“一致性”(又名:最终一致性)。

    如果这个操作失败了怎么办?

    仔细阅读Race Conditions Don't Exist; Udi Dahan 认为协作域中的操作不应该失败。

    在一个事务中更新所有聚合。

    你可以这样做;但这实际上意味着这两个实体实际上是单个隐式聚合的一部分。换句话说,它强烈表明您没有在正确的位置设置聚合边界。

    尝试在单个事务中修改多个聚合实际上是两阶段提交,由此产生的所有额外复杂性。

    什么都不做。只需记录和出错,然后等待人工干预。

    是的;例如,见; Greg Young 对 warehouse systems and exception reports 的看法。

    使用传奇。这使设计复杂化,并迫使我们实现每个用例,这些用例必须在单独的对象 (saga) 中的聚合之间强制执行不变量。

    如今,您通常会看到“流程管理器”而不是“saga”,后者具有更具体的含义。但是是的,如果域模型需要在聚合之间进行编排,那么您将需要在某处描述编排逻辑。

    您可能想查看 Rinat Abdullin 对Evolving Business Processes 的讨论;他提出了一个很好的论点,即自动化只是复制人类操作员会采取的行动。

    你会选择哪个选项,你的标准是什么?

    我更喜欢简单而不是简单。所以我的目标是异常报告,理由是(a)这些失败无论如何都应该很少见,所以我们不希望在远离幸福道路的工作上投入大量设计资金,以及(b)如果我们系统中有失败的命令,那么我们应该有一个机制来报告失败的命令无论如何,所以我只是利用已经存在的东西。

    如果我时间紧迫,如果项目还没有成功到需要扩展,如果我手头没有所需的报告部分,我可能更愿意将更改偷偷放入单个事务中,然后在开发过程本身中提出异常报告,以提醒人们注意以后需要完成更多工作。

    【讨论】:

      【解决方案2】:

      你会选择哪个选项,你的标准是什么 依据?

      1. 领域专家输入。如果他们始终要求极其严格的正确性,那么最终的一致性很可能不会成功。在其他时候,补偿操作需要手动干预,这在给定域中几乎不可行。或者,在循环中包含一个人可能非常简单和有益。与业务人员交谈将教会您更广泛的领域流程,并发现或排除一些选择。

      2. 事务分析。如果它们没有处于强并发访问之下,那么在单个事务中更新 2 个聚合可能不会有那么大的问题。相比之下,识别 "hot" aggregates 可以让您在重要的地方利用更松散的一致性。

      3. 用例复杂性。并非所有最终一致性场景都需要 Saga。如果操作很简单,例如根据事件更新聚合并在更新失败的不太可能发生的情况下回滚原始更改,那么您可能不需要如此复杂、长期存在的模式。

      【讨论】:

        猜你喜欢
        • 2020-10-19
        • 1970-01-01
        • 1970-01-01
        • 2020-06-08
        • 2012-11-24
        • 1970-01-01
        • 1970-01-01
        • 2013-08-24
        • 2019-02-05
        相关资源
        最近更新 更多