АрхитектураМикросервисы и интеграцииАрхитектор программного обеспечения

В двух микросервисах каждое изменение одной бизнес сущности требует согласованной правки их баз данных. Как...

В двух микросервисах каждое изменение одной бизнес-сущности требует согласованной правки их баз данных. Какой архитектурный вывод следует сделать?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

С высокой вероятностью граница между сервисами проведена неудачно: сервисы разделены технически, но не по самостоятельным бизнес-ответственностям. Если почти каждая операция требует атомарного изменения данных в обоих сервисах, их независимое развертывание и отказоустойчивость становятся формальными.

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

Исторический контекст

Микросервисный подход появился как способ разделять систему на независимо развиваемые и разворачиваемые части. Это позволяло командам автономно владеть бизнес-функциями, масштабировать их независимо и локализовать изменения.

Важна не сама физическая декомпозиция базы или кода, а граница ответственности. Идея ограниченного контекста из предметного моделирования предполагает, что внутри границы действуют свои термины, правила и модель данных, а взаимодействие с другими контекстами идёт через явный контракт.

Постановка проблемы

Если одна бизнес-операция регулярно меняет таблицы или внутренние данные нескольких сервисов, между ними возникает скрытая распределённая транзакция. При сбое между изменениями система может остаться в промежуточном состоянии, а восстановление потребует компенсаций, повторов или ручного вмешательства.

Такое разделение также усиливает связанность: изменение схемы или правила в одном сервисе заставляет синхронно менять другой. В результате растут задержки поставки, число интеграционных тестов и риск каскадных отказов, а независимость сервисов теряется.

Сам по себе общий бизнес-объект в разных сервисах не является ошибкой: разные контексты могут иметь собственные представления заказа, клиента или товара. Ошибка — когда эти представления должны изменяться атомарно при большинстве значимых операций.

Подробное решение

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

Затем следует проверить характер взаимодействия. Если операция действительно требует единой атомарной гарантии над данными обеих частей, это сильный аргумент в пользу одной границы сервиса или переноса общего инварианта внутрь одного владельца. Если же части могут согласовываться постепенно, их можно разделить и использовать события, команды или синхронные вызовы через стабильные контракты.

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

Компромисс выглядит так: объединение сервисов упрощает транзакции и согласованность, но уменьшает независимость масштабирования и поставки. Разделение повышает автономность, но требует контрактов, наблюдаемости, повторной обработки и модели временной рассогласованности.

Ситуация из практики

Команда разделила оформление заказа на сервис заказа и сервис резервирования товара. При подтверждении заказа оба сервиса должны были одновременно изменить свои записи: заказ переходил в состояние «подтверждён», а остаток товара уменьшался. При сбое между операциями появлялись подтверждённые заказы без резерва или зарезервированный товар без корректного состояния заказа.

Рассматривались три варианта. Общая база с одной транзакцией давала простую согласованность, но связывала сервисы схемой данных и лишала их автономности. Распределённая транзакция обеспечивала более строгую атомарность, однако усложняла инфраструктуру, восстановление и отказоустойчивость. Событийная схема с отдельным владельцем резерва позволяла каждому сервису владеть своей моделью, но требовала обработки промежуточных состояний и компенсации неуспешного заказа.

Выбрали третий вариант: резервирование стало отдельной бизнес-операцией, а заказ — процессом с явно описанными состояниями. Сервис заказа публиковал намерение оформить заказ, сервис резерва принимал решение и публиковал результат, после чего заказ переходил в подтверждённое или отменённое состояние.

Граница была признана удачной не потому, что исчезла вся временная рассогласованность, а потому, что каждый инвариант получил одного владельца. Сбои стали восстанавливаемыми, а сервисы — независимо изменяемыми.

Что кандидаты часто упускают

  1. Всегда ли общая сущность означает, что сервисы нужно объединить?

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

  1. Можно ли считать асинхронное событие заменой распределённой транзакции?

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

  1. Как отличить допустимую связанность от ошибочной границы?

Допустимая связанность проходит через стабильный бизнес-контракт: сервисы знают только нужные им команды, события или представления и могут развиваться независимо. Ошибочная граница проявляется в совместных изменениях схем, прямом доступе к чужой базе, обязательной синхронности большинства операций и необходимости одновременно выпускать несколько сервисов для одной бизнес-функции.