【问题标题】:Microservices, CQRS: Eventual consistency vs Strong consistency(Read after Write consistency)微服务、CQRS:最终一致性 vs 强一致性(读后写一致性)
【发布时间】:2018-06-25 22:35:03
【问题描述】:

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

【问题讨论】:

  • 给我一个用例示例。
  • 微服务 1:管理账户的利息 微服务 2:管理账户 微服务 2 使用利息板和持续时间进行账户管理,但是任何特定利息配置文件的任何更改最终都将仅适用于 MS2一致性,可能会发生在一个配置文件更改后开始的任何帐户处理都无法选择最新的配置文件,因为帐户微服务尚未更新。
  • 任何答案都提供了解决方案吗?
  • 我想这个问题没有灵丹妙药的答案,它归结为 CAP 定理,需要根据具体情况来考虑。

标签: microservices cqrs eventual-consistency


【解决方案1】:

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

但是,您可以使用Saga/Process manager 将关键操作建模为复杂流程。这意味着您使用 Saga 以您的业务可接受的方式协调操作的完成。例如,您可以使用类似Reservation pattern

这种模式可以在一个管理资源分配过程中 通过实施两遍协议来有序地进行 - 有点类似 到两阶段提交。在第一次通过期间,发起人询问每个人 参与者自行保留。如果发起者得到所有人的 OK 涉及的服务 - 在超时内 - 它将启动第二个 通过,向所有参与者确认预订。

【讨论】:

    【解决方案2】:

    在这种情况下,想想 C.A.P.定理。根据维基百科,“CAP 定理指出,在存在网络分区的情况下,必须在一致性和可用性之间进行选择。请注意,CAP 定理中定义的一致性与 ACID 数据库事务中保证的一致性完全不同。 "

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

    【讨论】:

      【解决方案3】:

      在这种情况下,每当 Account 上的任何活动开始时,它都可以从 Interest 微服务获取当前状态,这样您将始终保持同步,但您将使服务相互依赖,这样当 Interest Service Down 时,Account 服务将有效地下降。

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

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

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

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

      因此,请尝试确保系统更好地响应状态的可能性,而不是专注于微服务中的事务。但如果是的话,有对业务非常关键的需求,那就让他们依赖

      【讨论】:

        【解决方案4】:

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

        在我们的应用程序中,我们仍在寻找如何在不使用任何轮询器/调度器机制从系统/网络故障中恢复的情况下实现 100% 保证的最终一致性。

        【讨论】:

          【解决方案5】:

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

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

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

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

          简而言之,

          1. Kafka / Kinesis 作为微服务之间的事件协调器/代理
          2. 单分区和/或带密钥的消息(带日志压缩)
          3. 保留 [根据要求]
          4. 3 x 复制 [数据可用性]
          5. acks=all [高度数据一致性]

          【讨论】:

          • 如何提供一致性?
          • 这是最终的一致性(使用高性能队列 kafka 就是一个这样的例子,甚至可以使用 AKKA).. 问题是关于实现强一致性..
          猜你喜欢
          • 2015-06-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-20
          • 2016-11-19
          相关资源
          最近更新 更多