Следует ли использовать первичные ключи базы данных для идентификации сущностей в микросервисах?

Учитывая, что у меня есть два микросервиса: Service A и Service B.

Службе А принадлежат полные данные о клиентах, а службе Б требуется небольшое подмножество этих данных (которое она получает от службы А, скажем, через какую-то массовую загрузку).

Оба сервиса хранят клиентов в собственной базе данных.

Если службе B затем необходимо взаимодействовать со службой A, скажем, для получения дополнительных данных (например, GET /customers/{id}), ей явно нужен уникальный идентификатор, который используется двумя службами.

Поскольку идентификаторы являются идентификаторами GUID, я мог бы просто использовать PK из службы A при создании записи в службе B. Таким образом, оба PK совпадают.

Однако это звучит очень хрупко. Один из вариантов — сохранить «внешний идентификатор» (или «исходный идентификатор») в виде отдельного поля в службе B и использовать его для взаимодействия со службой A. И, вероятно, это строка, поскольку однажды она может не быть GUID.

Есть ли «лучшая практика» в этом отношении?

обновлять

Поэтому я провел еще несколько исследований и нашел несколько связанных обсуждений:

Следует ли раскрывать первичный ключ в URL-адресах REST API?

Является ли плохой практикой предоставлять идентификатор базы данных клиенту в вашем REST API?

Слаги как первичные ключи

заключение

Я думаю, что моя идея попытаться сохранить оба первичных ключа для клиента одинаковыми в службах A и B была просто неправильной. Это потому что:

  1. Очевидно, что PK зависят от реализации службы, поэтому они могут быть полностью несовместимы, например. UUID против автоматического увеличения INT.
  2. Даже если вы можете гарантировать совместимость, несмотря на то, что обе сущности называются «Клиент», они фактически являются двумя (потенциально очень разными) концепциями, и обе службы A и службы B «владеют» своей собственной записью «Клиент». Что вы можете сделать, так это синхронизировать некоторые данные о клиентах в этих службах.

Итак, теперь я думаю, что любая служба может предоставлять данные о клиенте через свой собственный уникальный идентификатор (в моем случае GUID PK), и если одной службе необходимо получить дополнительные данные о клиенте из другой службы, она должна хранить другой идентификатор/ключ службы и использовать это. Итак, по сути, вернемся к моей идее «внешнего идентификатора» или «идентификатора источника», но, возможно, более конкретно, как «идентификатор службы B».

Он не хрупкий, но необходимый. Даже если вы используете внешний идентификатор, не будет ли это значение по-прежнему храниться в службе A, чтобы соответствовать запросу от службы B?

Seth 12.12.2020 07:04

Да, мне, конечно, нужен внешний идентификатор, но мой вопрос заключался в том, использовать ли их в качестве первичных ключей базы данных в обеих службах. Мое предложение - нет, потому что это зависит от: а) PK в любой из служб не меняется (что не всегда может быть гарантировано) и б) уникальный идентификатор для клиента может быть, скажем, адресом электронной почты и, следовательно, не может использоваться в качестве База данных ПК. Так что я действительно ответил на свой вопрос здесь. Я действительно просто надеялся на блог или статью где-нибудь, которая просто подтвердит это.

Mark Chidlow 12.12.2020 10:01

Что ж, я думаю, это классный подход, которому мы можем следовать.

Tushar Mahajan 12.12.2020 11:04

Зачем вам это нужно в первую очередь? Если это клиент, у него, вероятно, есть идентификатор клиента, который компания использует внутри компании (например, для выставления счета или внутренней ссылки на клиента). Это ваше уникальное значение, которое вы также используете для вызова другой службы. GUID, автоинкремент и т. д. "первичный" ключ - это просто инструмент RDBM для моделирования отношений, который может отсутствовать в БД на основе документов. Представьте себе объект заказа и позиции заказа, для СУБД вам нужен столбец автоинкремента для моделирования отношений (т.е. присвоения позиции заказу).

Tseng 14.12.2020 09:34

Позиция также может иметь номер позиции, который обычно увеличивается и начинается с 1 для каждого нового заказа, но это не подходит для отношения FK. Теперь, когда у вас есть база данных документов, FK вообще не нужен, поскольку связь определяется структурой документа, то есть { "orderNumber": "O12345", "address": ..., "positions": [{ "positionNumber":1, "description": "Some Product", "priceNet": 10.00, ...].

Tseng 14.12.2020 09:38

Через rest API вы обычно указываете порядок как /orders/{orderNum}, а позиции как /orders/{orderNum}/positions и конкретную позицию: /orders/{orderNum}/positions/({positionNum}, поэтому нет необходимости раскрывать первичный ключ. P.S. однако лучше решать ваши проблемы с шиной сообщений, каждый раз, когда сущность в службе A изменяется, она запускает событие изменения в шину сообщений, служба B (и другие службы) выбирает свою копию события и обновляет сущность, поэтому ваш услуги не зависимы.

Tseng 14.12.2020 09:39

Наличие нескольких служб, синхронно вызывающих друг друга, не является микрослужбой. Это по-прежнему монолитное приложение, разделенное на несколько приложений. Одна служба становится недоступной, и все приложение перестает работать. Это противоположность духу микросервисов.

Tseng 14.12.2020 09:41
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Создание микрофронтендов с Angular и федерацией модулей в монорепо: Пошаговое руководство
Создание микрофронтендов с Angular и федерацией модулей в монорепо: Пошаговое руководство
Микрофронтенды стали популярным архитектурным паттерном для веб-разработки. С появлением федерации модулей в Webpack 5 реализация микрофронтендов...
7
7
2 056
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я думаю, это немного зависит от источника данных и вашего дизайна. Но одна вещь, которую я бы не стал раскрывать, — это первичный ключ, который представляет собой GUID или целое число с автоинкрементом для внешней службы. Это внутренние детали вашего сервиса, а не то, от чего должны зависеть другие сервисы.

Я бы предпочел иметь внешний идентификатор, который более понятен другим службам и, возможно, бизнесу в целом. Это может быть уникальный номер клиента, номер заказа или номер полиса, а не id. Вы также можете рассматривать их как «идентификатор компании». Следует также иметь в виду, что внешний идентификатор также может быть доступен конечному пользователю. Следовательно, это повсеместный способ идентификации этой «сущности» во всей организации и службах, независимо от того, используете ли вы Event-Driven-Design или ваши службы взаимодействуют через API. Я бы предоставил только идентификаторы БД инфраструктуре или репозиторию. Кроме того, это всего лишь бизнес/внешний идентификатор.

Что ж, если у вас есть представление о Value Object, бизнес-идентификатор будет намного лучше для разработки.

DDD фокусируется на бизнесе, чистый идентификатор UUID/автоинкремента не может его представить.

Используйте идентификатор бизнес-значения (идентификатор UL), например идентификатор клиента, вместо простого идентификатора.

Другие вопросы по теме