Microservices 是否应该使用数据库主键来标识跨微服务的实体?

Microservices 是否应该使用数据库主键来标识跨微服务的实体?,microservices,domain-driven-design,bounded-contexts,Microservices,Domain Driven Design,Bounded Contexts,假设我有两个微服务:服务A和服务B 服务A拥有完整的客户数据,而服务B需要这些数据的一小部分(例如,它通过一些批量加载从服务A获得) 这两种服务都将客户存储在自己的数据库中 如果服务B随后需要与服务A交互,比如获取额外数据(例如get/customers/{id}),那么它显然需要在两个服务之间共享的唯一标识符 因为ID是GUID,所以在服务B中创建记录时,我可以简单地使用服务A中的PK。因此两个PK都匹配 然而,这听起来非常脆弱。一个选项是将“外部Id”(或“源Id”)作为单独的字段存储在服务

假设我有两个微服务:服务A和服务B

服务A拥有完整的客户数据,而服务B需要这些数据的一小部分(例如,它通过一些批量加载从服务A获得)

这两种服务都将客户存储在自己的数据库中

如果服务B随后需要与服务A交互,比如获取额外数据(例如get/customers/{id}),那么它显然需要在两个服务之间共享的唯一标识符

因为ID是GUID,所以在服务B中创建记录时,我可以简单地使用服务A中的PK。因此两个PK都匹配

然而,这听起来非常脆弱。一个选项是将“外部Id”(或“源Id”)作为单独的字段存储在服务B中,并使用该字段与服务a交互。这可能是一个字符串,因为有一天它可能不是GUID

这方面有“最佳实践”吗

更新

所以我做了更多的研究,发现了一些相关的讨论:

结论

我认为我试图在服务A和服务B中保持客户的两个主键相同的想法是错误的。这是因为:

  • 显然,PK是特定于服务实现的,因此它们可能完全不兼容,例如UUID与自动递增INT
  • 即使您可以保证兼容性,尽管这两个实体碰巧都被称为“客户”,但它们实际上是两个(可能非常不同)的概念,服务A和服务B都“拥有”自己的“客户”记录。不过,您可能要做的是跨这些服务同步一些客户数据

  • 因此,我现在认为,任何一个服务都可以通过自己的唯一id(在我的例子中是PK GUID)公开客户数据,如果一个服务需要从另一个服务获取额外的客户数据,那么它必须存储另一个服务标识符/密钥并使用它。因此,基本上回到我的“外部id”或“源id”概念,但可能更具体地说是“服务B id”。

    我认为这取决于数据源和您的设计。但是,我要避免共享的一件事是主键,它是外部服务的GUID或自动递增整数。这些是您服务的内部细节,而不是其他服务应该依赖的内容


    我希望有一个外部id,这是更了解其他服务,也许是整个业务。它可以是唯一的客户编号、订单编号或保单编号,而不是
    id
    。你也可以把它们看作是“商业ID”。需要记住的一点是,外部id也可以向最终用户公开。因此,它是一种在整个组织和服务中识别“实体”的普遍方式,而不管您是否有事件驱动的设计,或者您的服务是否通过API进行通信。我只向基础设施或存储库公开DB ID。除此之外,它只是一个业务/外部id。

    好吧,如果您对价值对象有一个想法,那么业务id将更适合于设计

    DDD专注于业务,纯UUID/自动增量ID无法呈现


    使用业务含义ID(UL ID),如客户ID,而不是简单的ID。

    它不是脆弱的,而是必需的。即使使用外部id,该值是否也会存储在服务A中以匹配来自服务B的请求?是的,我当然需要外部id,但我的问题是是否在这两个服务中使用这些作为数据库主键。我的建议是否定的,因为这取决于a)任何一项服务的主键不改变(这可能并不总是得到保证)和b)客户的唯一标识符可能是电子邮件地址,因此不能用作数据库主键。所以我在这里真的回答了我自己的问题。我真的只是希望在某个地方能有一篇博客或文章来验证这一点。好吧,我想这是一个很酷的方法,只有我们可以遵循为什么你首先需要它?如果它是一个客户,它可能有一个公司内部使用的客户ID(即,在发票上或内部参考客户)。这是您的唯一值,您也可以使用它来调用其他服务。GUID、自动递增等“主键”只是用于建模关系的RDBM工具,在基于文档的数据库中可能不存在。假设一个订单和订单位置实体,对于RDBMS,您需要一个自动增量列来建模关系(即,将位置分配给订单)。该位置也可能有一个位置编号,通常每个新订单都从1开始计数,但这不适用于FK关系。现在,当您有一个文档数据库时,FK根本不需要,因为关系是由文档结构决定的,即
    {“orderNumber”:“O12345”,“address”:…,“positions”:[{“positionNumber”:1,“description”:“Some Product”,“priceNet”:10.00,…]