Назад к подготовке

Transactional outbox для БД и Kafka

Что делать, если бизнес-изменение записалось в БД, а событие в Kafka не отправилось?

Ответить самому

Сначала сформулируйте ответ как на собеседовании, затем откройте разбор и оцените себя.

Загрузка

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

В одной транзакции с бизнес-изменением записать событие в outbox-таблицу. Отдельный worker читает pending events, отправляет их в Kafka и помечает как sent с retry.

Полный разбор

Проблема dual write: БД и Kafka не участвуют в одной простой транзакции. Если сначала обновить БД, а потом отправить event, между этими шагами процесс может упасть. Если сначала отправить event, а потом не записать БД, потребители увидят событие про несуществующее состояние.

Transactional outbox решает это так: бизнес-изменение и запись event в outbox-таблицу происходят в одной DB transaction. После commit отдельный worker или CDC-процесс читает outbox, публикует события в Kafka и помечает их как sent. При сбоях он ретраит.

Потребителям все равно нужна идемпотентность, потому что delivery обычно at-least-once. Для порядка событий используют aggregate id, sequence/version и partitioning key.

Теория

Outbox переносит атомарность туда, где она есть: в транзакцию одной базы данных.

Типичные ошибки

  • Делать два независимых write без recovery-механизма.
  • Не делать consumers идемпотентными.
  • Не хранить статус и retry count outbox-события.