微服务:如何处理外键关系

时间:2017-07-02 11:45:53

标签: database microservices

微服务架构建议每个服务都应该处理它自己的数据。因此,依赖于其他服务(服务B)拥有的数据的任何服务(服务A)都应该访问这些数据,而不是通过直接数据库调用,而是通过第二服务(服务B)提供的API。

那么微服务最佳实践在检查外键约束方面的建议是什么。

示例:我正在为产品开发交付功能(微服务1),某些产品只能交付给产品表中提到的某些位置,只能访问产品微服务(mircoservice 2)。

如何确保微服务1(即交付功能)不接受订购到未服务的位置。我有这个问题,因为交付功能无法直接访问产品数据库,因此当交货订单放入交货数据库时,没有适用于数据库级别的限制(无法检查产品数据库中是否存在外键匹配)或表)。

4 个答案:

答案 0 :(得分:33)

可以将共享数据库用于多个微服务。您可以在此链接中找到微服务数据管理的模式:http://microservices.io/patterns/data/database-per-service.html。顺便说一下,它是微服务架构的一个非常有用的博客。

在您的情况下,您更喜欢使用每个服务模式的数据库。这使微服务更加自主。在这种情况下,您应该在多个微服务中复制一些数据。您可以使用微服务之间的api调用共享数据,也可以使用异步消息传递来共享数据。这取决于您的基础架构和数据更改频率。如果不经常更改,则应使用异步事件复制数据。

在您的示例中,送货服务可以复制送货地点和产品信息。产品服务管理产品和位置。然后使用异步消息将所需数据复制到Delivery Service的数据库(例如,您可以使用rabbit mq或apache kafka)。交付服务不会更改产品和位置数据,但会在数据执行时使用数据。如果交付服务使用的产品数据部分经常发生变化,那么使用异步消息传递进行数据复制将非常昂贵。在这种情况下,您应该在产品和交付服务之间进行api调用。交付服务要求产品服务检查产品是否可交付到特定位置。交付服务向产品服务询问产品和位置的标识符(名称,ID等)。这些标识符可以从最终用户获取,也可以在微服务之间共享。由于微服务的数据库在这里不同,我们无法在这些微服务的数据之间定义外键。

Api调用可能更容易实现,但此选项中的网络成本更高。当您进行api呼叫时,您的服务也不那么自主。因为,在您的示例中,当产品服务关闭时,交付服务无法完成其工作。如果使用异步消息传递复制数据,则传递所需的数据位于Delivery microservice的数据库中。当产品服务无法运作时,您将能够进行交付。

答案 1 :(得分:11)

在分发代码以实现减少耦合时,您希望避免资源共享,并且数据是您希望避免共享的资源。

另一点是系统中只有一个组件拥有数据(用于状态更改操作),其他组件可以READ但不写,他们可以拥有数据副本,或者您可以共享他们可以用来获取的视图模型对象的最新状态。

引入引用完整性将重新引入耦合,而您希望为主键使用Guids之类的东西,它们将由对象的创建者创建,其余的都是关于管理最终一致性。

看看Udi Dahan的talk in NDC Oslo for a more details

希望这有帮助

答案 2 :(得分:2)

第一个解决方案:API Composition

 Implement a query by defining an API Composer, which invoking the
 services that own the data and performs an in-memory join of the
 results

enter image description here

第二个解决方案:CQRS

Define a view database, which is a read-only replica that is designed to support that 
query. The application keeps the replica up to data by subscribing to Domain events 
published by the service that own the data.

enter image description here

答案 3 :(得分:1)

对此答案的2020年更新是使用像Debezium这样的Change Data Capture工具。 Debezium将监视您的数据库表中的更改并将其流式传输到Kafka / Pulsar(其他管道),然后您的订户可以捕获更改并同步它们。