微服务,CQRS:最终一致性与强一致性(写后一致性读取)

时间:2018-01-17 05:57:17

标签: microservices cqrs eventual-consistency

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

5 个答案:

答案 0 :(得分:4)

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

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

的内容
  

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:0)

在微服务领域无法实现强一致性。一旦破坏了数据存储,就失去了强大的一致性。

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

答案 3 :(得分:0)

在这种情况下,无论何时在Account上启动任何活动,它都可以从Interest微服务中获取当前状态,这样,您将始终保持同步,但是您将使服务彼此依赖,以便当Interest Service Down时,Account服务将有效地降低情绪。

仔细考虑一下您的问题,我认为您需要考虑的是一致性是否如此重要(我提出这个问题是因为当来自整体或交易背景时,我们倾向于认为存在一致性)。

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

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

另一个解决方案是在下订单时不检查客户ID,而是在OrderPlace事件上检查客户ID并采取必要的操作。

因此,请尝试确保系统更好地响应状态的突发事件,而不是专注于微服务中的事务。但是,如果是的话,那么对于业务而言非常关键的需求就可以使之依赖

答案 4 :(得分:-2)

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

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

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

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

简而言之,

  1. Kafka / Kinesis作为微服务之间的事件编排者/经纪人
  2. 单个分区和/或带密钥的消息(带日志压缩)
  3. 保留[根据要求]
  4. 3 x复制[数据可用性]
  5. acks =所有[高水平的数据一致性]