如何解决事件存储和持久层之间的两个常规问题



两个常见问题 - 事件存储和持久层?

我想了解行业实际上是如何处理这个问题的!

如果微服务 1 将对象 X 保存到数据库 A 中。同时,为了使微服务 2 以微服务 1 中的数据为源,微服务 1 将相同的对象 X 写入事件存储 B。

现在,我的问题是,我首先在哪里写对象 X?

  1. 首先是数据库 A,然后是事件存储 B,如果数据库 A 关闭,在应用程序级别回滚线程是否公平?此外,如果数据库 A 处于联机状态并且持久化对象 X 但事件存储 B 已关闭,理想的错误句柄应该是什么?

  2. 如果我们对第 1 点反之亦然,错误句柄应该是什么样子?

我确实理解,在当今分布式高可用性系统的世界中,系统出现故障是值得怀疑的事情。但是,它可能会发生。我想了解当数据库或事件存储系统/群集关闭时需要做什么?

通常,您希望避免依赖您所描述的那种两阶段提交。

一般来说,(假设一个事件源系统;不确定这是否隐含在你的问题/你的一个选项中 - 也许SqlStreamStore可能与你的上下文相关?),这通常是通过从一组权威事件中project拉来管理的 - 每个正在编写的事件都需要对某个下游执行关联操作,维护一个指针,指向它从基本流中投影事件的程度, 并在中断时从那里重新启动。

首先,事件存储是一种持久性,它将应用程序状态存储为一系列事件,而不是存储最后一个投影状态的平面持久性。

如果微服务 1 将对象 X 保存到数据库 A 中。同时,为了使微服务 2 以微服务 1 中的数据为源,微服务 1 将相同的对象 X 写入事件存储 B。

您正在尝试拥有两个事实来源,这些事实来源必须通过某种可扩展性不高的分布式事务保持同步。

这是使用事件存储的一种不寻常模式。通常,事件存储是规范的信息源,即单一的事实来源。您正在尝试将其用作通信渠道。事件存储是事件源聚合的持久性(请参阅域驱动设计)。

我看到选项:

  1. 您可以重构体系结构,并使object X和事件源实体具有事件存储的持久性。然后让读取模型订阅事件存储,并构建持久保存在数据库 A 中的object X的平面表示形式。换句话说,首先写入事件存储,然后写入数据库 A(但以最终一致的方式!这是一个很大的飞跃,你应该真正考虑是否要去事件源。

  2. 可以在没有事件溯源的情况下使用 CQRS。这意味着,每次修改后,object X都会发出一个或多个域事件,这些事件与object X本身相同的本地事务中持久保存在数据库 A 中。微服务 2 可以订阅数据库 A 以获取发出的事件。实际订阅取决于数据库的类型。

我有一种感觉,你正在使用事件存储作为通信渠道,而不是将其用作数据库。如果希望微服务 2 以微服务 1 中的数据为依据,则应与 REST 服务通信。

当然,依赖 REST 服务可能会降低您对中断的弹性。在这种情况下,使用专用于通信的技术将是正确的方法。(我在想 MQ/Topics,比如 RabbitMQ、Kafka 等)

然后,一旦您的服务相互通信,您仍然需要保留您的数据...但仅限于一个位置。 因此,您需要定义要存储数据的位置

问问自己:

谁将负责数据持久性的治理?

  • 如果是这样,那么每次 Microservice2 需要读取数据时,它都会对 Microservice1 进行 REST 调用。
  • 是反过来吗?微服务2拥有数据的治理权,微服务1消耗数据?

  • 它可能是您尚未创建的第三个微服务。这取决于您如何应用关注点分离。

让我们举个例子:

  • Microservice1 的职责是处理我们的数据,以 PDF 和其他格式导出
  • Microservice2 的职责是为传统合作伙伴公开服务,这需要我们的数据以非常专有的表示形式返回。

谁将在这里存储数据?

  • 微服务1不应该是持久化数据的人:它的工作只是将数据转换为其他格式。如果它需要一些数据,它将从具有数据治理权的那个数据中获取它们。
  • 微服务2不应该是持久保存数据的人。毕竟,也许我们还有许多其他与此类似的微服务,但对于其他合作伙伴,具有不同的专有格式。
  • 如果有一项服务可以进行 CRUD 操作,那就是您的人。如果你没有这样的服务,也许你可以找到一个现有的微服务,它不会有冲突的责任。

例如:如果我有一个 Microservice3,确保每次更改我的ObjectX时,它都会将其的 PDF 表示形式发送到某个地址,并通知我的所有合作伙伴数据已过期。在这种情况下,此微服务看起来是一个很好的候选者,可以成为这部分域的"数据调控器",并成为在数据库中写入/读取的一站式商店。

最新更新