Как организовать транзакционность в микросервисной архитектуре при работе с разными базами данных
Что проверяют
Понимаете ли вы, что ACID-транзакции через границу сервисов нет, и знаете ли, чем её заменяют на практике. Следом почти всегда спрашивают, как не потерять событие, если сервис записал данные и упал до отправки сообщения.
Как отвечать
Начните с вывода: у каждого сервиса своя база, общий BEGIN ... COMMIT невозможен, поэтому согласованность достигается в конечном счёте, а атомарность обеспечивает процесс, а не база.
- Saga: цепочка локальных транзакций, у каждого шага есть компенсация. Заказ создан, товар зарезервирован, оплата не прошла, значит снимаем резерв и отменяем заказ. Бывает оркестрацией (координатор знает сценарий и хранит состояние) и хореографией (сервисы реагируют на события друг друга). Для длинных сценариев оркестрация прозрачнее; в Node.js её пишут поверх очереди или берут Temporal с TypeScript SDK;
- Transactional Outbox: в одной локальной транзакции сервис пишет бизнес-данные и строку в таблицу
outbox. Отдельный процесс или CDC вроде Debezium публикует её в Kafka или RabbitMQ. Запись и событие не расходятся; - идемпотентные потребители: доставка «хотя бы один раз» означает дубли, поэтому обработчик хранит id обработанных сообщений;
- промежуточные статусы: заказ в
PENDING, пока сага не завершилась, чтобы никто не видел полуготовое состояние; - 2PC: prepare и commit через координатора. На практике почти не используется: держит блокировки, зависит от координатора, а многие брокеры и NoSQL-базы в нём не участвуют.
Сильный ответ заканчивается вопросом о границах: если две сущности всегда меняются атомарно, возможно, им место в одном сервисе.
Где спотыкаются
Публикуют событие в брокер сразу после COMMIT без outbox. Падение процесса между двумя вызовами даёт данные без события.
Пишут компенсации, которые нельзя выполнить: отправленное письмо или платёж у внешнего провайдера не откатить, нужны отдельные действия вроде возврата.
Называют CQRS решением транзакционности. Это разделение моделей чтения и записи, к атомарности между сервисами оно отношения не имеет.