我正在尝试为我公司处理订单管理的一些简单内部系统建立一个实用的微服务演示,但是我很难理解大规模时微服务之间的数据一致性。
我已经确定了微服务的一种简单情况-我们正在使用的当前应用程序正在处理网站上的订单并更新客户的“帐户信用额”-基本上,他们可以在使用帐户前花在我们身上的未付款项需要进行审核。
我试图将这个非常简单的需求分解为几个微服务。这些定义如下:
API提供了各种不同级别的功能-它使我们能够创建新客户,并触发以下内容:
使用SQL,我们可以在数据库中进行操作时进行一些乐观查询,以尝试通过缩放微服务来确保同时处理两个订单(例如:订单微服务的两个实例,每个微服务但不每个微服务实例都有自己的数据库。
例如,我们可以执行以下操作,并假定SQL将管理锁定,这意味着当同时处理两个订单时,该数字应以正确的数字结尾:
UPDATE [orderms].[customers] SET CreditLimit = CreditLimit - 100, NoOfOrders = NoOfOrders + 1 WHERE CustomerId = 1
使用上述方法,如果贷项为1000,并且处理了2个订单(每个订单100个),并且每个订单都分配给“ Order”微服务的不同实例,那么我们应该能够假定正确的数字会出现在订单微服务中的customers表(基于MSSQL查询的锁定应自动处理)。
然后,当我们尝试将它们重新集成到客户微服务时,问题就来了。我们将收到两条消息,来自作为事件传递的订单微服务的每个实例,如下所示:
鉴于上述情况-我们很可能会按照以下方式(以下是两个查询)遵循更新“客户” SQL表的模式:
UPDATE [customerms].[customers] SET CreditLimit = 900.00 WHERE CustomerId = 1
UPDATE [customerms].[customers] SET CreditLimit = 800.00 WHERE CustomerId = 1
但是-根据这些“客户”微服务的运行速度,实例1目前可能正在创建多个新客户,因此处理该请求的速度可能比实例2慢,这意味着SQL查询将会无序执行,因此我们将剩下“信用”限制为800(正确)的“订单”数据库和“信用限制”为900(错误)的客户微服务。
在整体应用程序中,如果确实需要,我们通常会添加一个锁元素(或可能是Mutex),否则根据Order Microservice中的功能依赖于SQL锁,但是由于这是一个分布式过程,这些较旧的方法都不适用。
有什么建议吗?我似乎无法以某种方式看到过去?
答案 0 :(得分:1)
我认为解决方案
在两个微服务中都维持初始信用额度。假设初始信用额度为1000,然后在两个Microservices数据库中进行设置。在处理订单时,首先在订单微服务处将其减少,而不是发送信用额度(800,900或任何金额),而是发送必须从客户微服务信用额度中减少的金额。
说您已经处理了两个订单,每个订单价值100。首先降低微服务订单的信用额度,然后生成两个每笔100美元的事件,这些事件将由客户服务部门消费,并在该事件减少。这样,无论它们到达的顺序如何,您都只需要减少该数量即可。
事件来源(更好的方法)
采用乐观锁定的事件来源是您可以采取的方法。这种模式是将所有事件保存在数据库中,而不是保存实体的特定状态。它只是一个追加存储,事件按它们到达的顺序存储。在这种情况下,您需要重播事件以达到特定状态的信用额度。在这种情况下,您将拥有所有历史记录。请记住,如果有任何不一致的地方,您没有任何日志可以回退,但是有了事件源,您就有了。