代码之家  ›  专栏  ›  技术社区  ›  w0051977

1)域事件与事务一致性和2)集成事件与最终一致性之间的关系

  •  1
  • w0051977  · 技术社区  · 6 年前

    我理解事务一致性和最终一致性之间的区别。假设我正在开发一个应用程序,其中有三个微服务和一个消息总线,当引发集成事件时,消息总线在它们之间发送消息,这意味着最终的一致性。例如,microservice b发布一个集成事件,microservice a两小时后处理它,因为microserviceb在事件发布时已关闭,并且消息是持久的—这很好。

    我的理解是:微服务内部应该有事务一致性-聚合A可以发布聚合B感兴趣的域事件,因此引发域事件并在同一事务中执行对数据库的任何更新。

    我不理解cqrs如何适应这种事务一致性/最终一致性场景,因为:

    1. 我不能使用事务一致性,因为读取模型(nosql)和写入模型(sql server)不能在同一事务中更新。
    2. 我无法使用消息总线,因为更新读取模型不是集成事件,即读取模型和写入模型包含在同一个微服务中。

    对于CQR,我认为有两种选择:

    1. 如果对写端使用事件存储,那么读端可以轮询它—这解决了问题,因为没有事件。
    2. 如果在写端使用事件日志/关系数据库,则会引发域事件来更新读端。

    如果选择了选项2,那么我如何保证读取模型最终将与写入模型同步?例如,在引发事件时,读取模型可能已关闭。

    3 回复  |  直到 6 年前
        1
  •  2
  •   Allan Chua    6 年前

    在只读系统中使用dbms系统时,cqrs通过降低乐观锁的漏洞,符合最终一致性的概念。分离命令和查询使您能够进行工作读/写,而不管这两者的可用性如何。

    1)。如果由于乐观锁定而希望拥有高可用的终结点,则事务一致性是不可取的。

    2)。您绝对可以使用消息总线来更新您读取的模型,因为排队的概念不是上下文间数据同步的同义词。

        2
  •  0
  •   aschuell    6 年前

    从技术上讲,聚合是ddd中原子性的单位,因此不需要保证通过域事件进行通信的聚合之间的一致性。从埃文的书中:

    聚合是关联对象的群集,我们将其视为 用于数据更改的单位…不变量,它们是 数据更改时必须维护的一致性规则 涉及聚合成员之间的关系。任何规则 Spans聚合不会一直是最新的 …但在聚合中应用的不变量将被强制 完成每笔交易。

    不过,出于实际目的,我开发的大多数服务 在为处理初始请求而创建的相同环境事务中包装域事件的处理。分布式应用程序很难设计和调试而不必担心补偿操作之类的问题 里面 服务!

    我正在使用 MediatR 将域事件处理程序与生成它们的原始命令/请求处理程序分离的库。它与消息传递系统具有非常相似的发送/处理语义,并包括一个健壮的中间件,如用于验证和前/后处理的管道。

        3
  •  0
  •   choquero70    6 年前

    如果选择了选项2,那么我如何保证读取模型最终将与写入模型同步?

    解决方案是两种选择的混合:

    • 执行命令时引发域事件。

    • 将域事件存储在写入模型的事件存储中。此任务由静态轻型订阅服务器生成。事件存储在执行命令的同一事务中。

    • 工作进程或批处理进程获取事件存储的事件并通过消息队列发送它们。

    • 订户将它们从队列中取出并更新读取模型。

    这样你就永远不会输掉比赛。如果读取模型由于任何原因不可用,则工作人员将再次重新触发该事件。