微服务、CQRS:最终一致性 vs 强一致性(Read after Write consistency)

Microservices, CQRS: Eventual consistency vs Strong consistency(Read after Write consistency)

使用 CQRS 和事件存储,微服务之间的编排提供了最终的一致性,其中一个微服务中的更改需要一点时间才能传播到相关的其他下游系统(基本上是其他微服务)。 如果数据非常重要以至于两个微服务都应该对数据具有强一致性,有什么选择?我能想到的一种选择是像数据网格一样通过缓存写入,但这在分布式系统中特别脆弱。

您可以使用 Kafka 或 Kinesis 来编排关键数据更新的 2 个微服务之间的事件一致性。例如,微服务 1 [MS1] 对事件的反应会触发主题中的适当消息,然后 MS2 会立即读取该消息。

这种方法的其他好处是,如果有多个 MS 依赖于 MS1 的反应,那么所有其他 MS 都可以获得该事件。

如果事件是完整的和幂等的,那么您也可以启用日志压缩(虽然不是必需的)以在一段时间内始终获得最新的副本。

注意:但是,请确保仅在 Kafka 主题中使用一个分区,因为 Kafka 中的顺序保证仅针对每个分区,或者始终向消息添加密钥,以便它们落入同一分区。

简而言之,

  1. Kafka / Kinesis 作为微服务之间的事件orchestrator/brokers
  2. 单个分区and/or带键的消息(带日志压缩)
  3. 保留[根据要求]
  4. 3 x 复制 [数据可用性]
  5. acks=all [数据一致性高]

强一致性在分布式服务中很难,而在微服务中更难,因为它们拥有自己的数据。这意味着您只能在微服务内部拥有强一致性。

但是,您可以使用 Saga/Process manager. This means that you use a Saga to orchestrate the completion of the operation in a manner that is acceptable by your business. For example you could use something like the Reservation pattern

将关键操作建模为一个复杂的过程

This pattern enables managing the resource allocation process in an orderly manner by implementing a two pass protocol - somewhat similar to a two phase commit. During the first pass, the initiator asks each participant to reserve itself. If the initiator gets an OK from all the involved services - within a timeout - it will start the second pass, confirming reservation to all the participants.

在这种情况下,想想C.A.P。定理。根据维基百科,"the CAP theorem states that in the presence of a network partition, one has to choose between consistency and availability. Note that consistency, as defined in the CAP theorem, is quite different from the consistency guaranteed in ACID database transactions."

因为你有 2 个微服务,所以你的系统肯定需要分区容错,你只能选择 A(可用性)或 C(一致性)。如果您想使用 C,那么您的系统将在可用性方面受到影响。当请求进入微服务 A 时,您不应该向客户端发送成功消息,直到 A 从微服务 B 返回数据已成功存储的响应。通过这种方式,您可以通过牺牲可用性来实现一致性。

在微服务环境中无法实现强一致性。一旦你分解了数据存储,你就失去了强一致性。

在我们的应用程序中,我们仍在寻找如何实现 100% 有保证的最终一致性,而不使用任何 poller/scheduler 机制从 system/network 故障中恢复。

在这种情况下,只要任何 activity 在帐户上启动,它就可以从 Interest 微服务中获取当前状态,这样您将始终保持同步,但您将使服务相互依赖,这样当 Interest 时Service Down ,账号服务将有效宕机

看了你的问题,我认为你需要考虑的是一致性是否如此重要(我提出这个问题是因为当我们来自整体或事务背景时,我们倾向于认为一致性是存在的)。

例如:假设您在亚马逊上下订单并且需要发送客户 ID,在这种情况下您应该检查客户 ID 是否有效。

这将使订单服务依赖于客户服务。

另一种解决方案是在下订单时不检查客户 ID,而是在 OrderPlace 事件中检查它并采取必要的措施。

所以尽量确保系统更好地响应状态的最终性,而不是专注于微服务中的事务。但如果是,则存在对业务非常关键的需求,然后让它们依赖