Две системы должны обмениваться данными о сделках с гарантией доставки. Спроектируйте обмен: что выберете и как обеспечите надёжность и согласованность?
Короткий ответ
- Уточнить: объёмы, допустимая задержка, кто источник правды
- Асинхронный обмен событиями через брокер сообщений
- Transactional outbox: событие пишется в одной транзакции с данными
- At-least-once доставка плюс идемпотентный потребитель
- DLQ и алерты для необработанных сообщений
- Сверка (reconciliation) по расписанию ловит расхождения
- Версионирование схемы событий для эволюции контракта
Надёжный обмен строится на событиях через брокер с transactional outbox на стороне источника, идемпотентным потребителем, DLQ и регулярной сверкой как последней линией защиты.
Как сказать вслух
пример ответаСначала уточню объёмы, допустимую задержку и какая система — источник правды по сделкам. Для гарантии доставки выберу асинхронный обмен событиями через брокер. Ключевая проблема — не потерять событие между записью в базу и отправкой, её решает паттерн outbox: событие сохраняется в той же транзакции, что и сделка, а отдельный процесс публикует его в брокер. Доставка получается «минимум один раз», значит потребитель должен быть идемпотентным. Плюс очередь недоставленных сообщений с алертами и регулярная сверка данных как страховка.
Подробный ответ
Основной ответ
Сначала контекст: объёмы и пики, допустимое окно рассинхронизации, направление потоков, какая система мастер по сделкам, требования аудита. Для гарантированной доставки — асинхронный обмен событиями (DealCreated, DealUpdated) через брокер (Kafka, RabbitMQ). Слабое место — двойная запись: сохранить сделку в БД и опубликовать событие атомарно нельзя. Решение — transactional outbox: событие пишется в таблицу outbox в одной транзакции с бизнес-данными, отдельный публикатор переносит его в брокер. Это даёт at-least-once, поэтому потребитель дедуплицирует по идентификатору события или версии сущности и применяет изменения идемпотентно; порядок обеспечивается партиционированием по ключу сделки. Необработанные сообщения после ретраев уходят в DLQ с алертами. Последняя линия защиты — регулярная сверка (reconciliation): сравнение данных систем по расписанию с отчётом о расхождениях. Контракт события версионируется, изменения — обратно совместимые.
Ключевые моменты
- Transactional outbox. Событие сохраняется в одной транзакции с данными, публикатор отправляет его в брокер — исключает потерю между записью и отправкой.
- Идемпотентный потребитель. At-least-once означает дубли; потребитель дедуплицирует по id события и игнорирует устаревшие версии сущности.
- Порядок событий. События одной сделки идут в одну партицию по ключу, иначе обновления могут примениться не по порядку.
- Сверка как страховка. Регулярная reconciliation по ключевым полям ловит расхождения, которые просочились мимо всех гарантий.
Практический контекст
Такой кейс дают на senior-позиции системного аналитика по интеграциям. Проверяют знание проблемы двойной записи и паттерна outbox, понимание гарантий доставки и честность про eventual consistency: сильный кандидат сам проговаривает, что exactly-once в общем случае недостижим, и компенсирует это идемпотентностью и сверкой. Слабый ответ — «поставим Kafka, она надёжная» без разбора краевых сценариев.
Частые ошибки
- Игнорируют проблему атомарности записи в БД и публикации события
- Обещают exactly-once доставку вместо идемпотентной обработки at-least-once
- Забывают про порядок событий и про сверку данных как последнюю защиту