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

Should database primary keys be used to identify entities across microservices?

鉴于我有两个微服务:服务 A 和服务 B。

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

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

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

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

然而,这听起来非常脆弱。一种选择是将 'external Id'(或 'source id')作为服务 B 中的单独字段存储,并使用它与服务 A 交互。可能这是一个字符串,因为有一天它可能不是GUID.

这附近有'best practice'吗?

更新

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

Slugs as Primary Keys

结论

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

  1. 很明显,PK 是特定于服务实现的,因此它们可能完全不兼容,例如UUID 与自动递增的 INT。
  2. 即使您可以保证兼容性,尽管这两个实体恰好都被称为 'Customer' 它们实际上是两个(可能非常不同的)概念,服务 A 和服务 B 都是 'own' 它们的拥有 'Customer' 记录。不过,您可能想要做的是在这些服务之间同步一些客户数据。

所以我现在认为任何一个服务都可以通过它自己的唯一 ID(在我的例子中是 PK GUID)公开客户数据,如果一个服务需要从另一个服务获取额外的客户数据,它必须存储另一个服务 identifier/key 并使用它。所以基本上回到我的 'external id' 或 'source id' 想法,但也许更具体如 'service B id'.

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

我宁愿有一个外部 ID,它更容易被其他服务甚至整个企业理解。它可以是唯一的客户编号、订单编号或保单编号,而不是 id。您也可以将它们视为“企业 ID”。还要记住的一件事是,外部 ID 也可以暴露给最终用户。因此,它是一种在整个组织和服务中识别该“实体”的普遍方式,无论您是否拥有事件驱动设计或您的服务是否通过 API 进行对话。我只会将数据库 ID 公开给基础设施或存储库。除此之外,它只是一个企业/外部ID。

好吧,如果您对值对象有想法,那么业务 ID 将更好地用于设计。

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

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