微服务架构中如何处理“外键”?

时间:2020-07-15 17:55:27

标签: spring-boot microservices

有关微服务中外键的快速问题。我已经尝试寻找答案。但是,他们没有给我我想要的确切答案。

用例:每个博客帖子都会有很多评论。传统的整体版将在博客表中添加带有外键的注释表。但是,在微服务中,我们将提供两种服务。

服务1:使用这些表格字段(PostID,名称,内容)发布Microservie

服务2:使用以下表字段(CommentID,PostID,Cpmment)注释Microservie

问题是,我们在服务2(注释微服务)中是否需要“ PostID”?我想答案是肯定的,因为我们需要知道哪个评论属于哪个帖子。但是,这会产生紧密的耦合吗?我的意思是,如果我删除服务1(博客发布服务),会影响服务2(评论服务)吗?

1 个答案:

答案 0 :(得分:4)

我将使用另一个我更熟悉的示例来解释我相信大多数人会如何做。

考虑订单管理系统(OMS)和库存管理系统(IMS)。

当客户在公司网站上下订单时,我们要求OMS在后端(例如,通过HTTP端点)创建订单条目。

OMS系统随后广播一个事件,例如OrderPlaced包含客户订单的所有详细信息。我们可能会在其中放置事件的发布/订阅(例如Redis),队列(例如RabbitMQ)或事件流(例如Kafka)(尽管这可以通过许多其他方式完成)。

问题是,我们有一个或多个订阅者对此事件感兴趣。 IMS就是其中之一。IMS负责在每次下订单时分配最佳的可用库存。

我们可以预期,IMS将保留在处理OrderPlaced事件时收到的相关订单信息的副本,这样它就不会一直向OMS询问订单的每一个细节。因此,如果IMS需要与订单进行联接,而不是在Order API中调用端点,则可能只对订单表的本地副本进行联接。

现在说我们的客户打电话取消她的订单。然后,客户服务代表在OMS Web用户界面中将其取消。此时,将广播事件OrderCanceled。猜猜谁在听那个事件?正确,IMS会收到通知,并采取相应的措施来撤销库存分配,甚至可能删除订单记录,因为该域不再需要该记录。

因此,如您所见,最好的方法是使用事件并在另一个域上复制相关详细信息。

由于事件需要时间进行广播并由感兴趣的各方进行处理,因此我们说IMS中的订单数据最终是一致的。

后续问题

问:那么,如果我对微服务理解得很好,我们希望复制数据并获得更好的性能?那是概念吗?我的意思是我知道概念是可扩展性和灵活性,但是当我们必须共享数据时,我们将复制它吗?

不是。那绝对不是我的意思,虽然听起来可能是由于我在原始说明中用词不当所致。在我看来,您的问题的核心是对bounded context的概念缺乏足够的理解。

在我的解释中,我的意思是指出OMS具有称为订单的域概念,而IMS也是如此。因此,它们在域中都有一个表示它的实体。 OMS中的订单实体很有可能比IMS中相同概念的对应表示丰富得多。

例如,如果我描述的系统不是零售的,而是批发的,那么我们系统中“销售订单”的相同概念就相当于我们客户的“购买订单”的概念。因此,您看到的是,以相同名称映射的相同数据,仅仅是因为在不同的有界上下文中,数据可能具有不同的视角和含义。

因此,这是意识到我们模型中的给定概念可以在多个有限上下文中表示,也许是从ubiquitous language的不同角度和名称来表示。

再举一个例子,OMS需要了解客户,但是OMS中客户想法的表示可能不同于CRM中这种概念或实体的表示。在OMS中,客户的姓名,电子邮件,运送和帐单地址可能足以表示此想法,但对于CRM,客户包含的内容更多。

另一个例子:IMS需要知道客户的送货地址以选择最佳库存(例如,最接近其最终目的地的设施中的那个),但可能不太在意帐单地址。另一方面,帐单地址是付款管理系统(PMS)的基础。因此,IMS和PMS都可能具有“顺序”的概念,只是它并不完全相同,即使我们存储相同的数据,也没有相同的含义或观点。

最后一个例子:会计系统出于核算目的关心库存,以便能够告诉我们我们拥有多少库存,但也许核算并不关心仓库中库存的特定位置,这仅是详细信息。 IMS在乎。

总而言之,我不会说这与“复制数据”有关,这是关于在有限的上下文中适当地表示一个基本概念,以及意识到模型中的某些概念可能在系统之间重叠并且具有不同的表示,有时甚至在不同的名称和级别下。因此,我建议您进一步研究context mapping的想法。

换句话说,从我的角度来看,假设“订单”的概念仅存在于OMS中是错误的。我可能会说OMS是订单记录的主控者,如果订单发生问题,我们应该让其他感兴趣的系统知道这些事件,因为它们关心某些数据,因为其他系统可能具有与之相关的映射概念。订单,并且对记录母版中的更改做出反应时,他们可能还希望更改其数据。

从这个角度来看,复制某些数据是为有限上下文(而不是目标)进行适当设计的副作用。

我希望能回答您的问题。