TGViewer
Женя Янченко Женя Янченко @jane_yanchenko · 5.51K subscribers
Post #279 4.78K
Это произошло, когда я только недавно пришла в новую компанию лидом.
Мы начали новый проект, и одному из сервисов требовалось:

1️⃣ принимать поток данных
2️⃣ сохранять их в БД
3️⃣ некоторые из них отправлять дальше в Кафку

Идёт обсуждение сервиса. Терять данные нельзя. Как быть?

🤔 Допустим, мы будем сохранять данные в БД, комитить транзакцию, а потом отправлять в Кафку. Но если приложение вдруг упадет, не успев отправить данные, то окажется, что данные в БД есть, а дальше мы их не отправили. Так нельзя.

🤔 Ок, тогда давайте не будем закрывать транзакцию после сохранения в БД, а оставим её открытой пока не отправим в Кафку. Если с отправкой все хорошо — закоммитим транзакцию. А если брокер будет недоступен и нужны повторные попытки? Будем удерживать транзакцию? Плохо.

🤔 А если уже после отправки в момент коммита транзакции произойдет ошибка в БД, и транзакция откатится? Получается мы данные отправим, а себе не сохраним. Так тоже нельзя.


Пазл не складывается. Я понимаю, что наверняка не мы первые столкнулись с такой задачей и у меня в памяти всплывает, что есть паттерн как раз для этого. Вспоминаю суть, но не могу вспомнить название!

Свежеиспечённому лиду не пристало ударять лицом в грязь и нужно срочно выдать решение 🙈 Начинаю нервничать и от этого никак не могу поймать ускользающее название. Что-то с транзакциями и таблица там специальная.

Ситуацию осложняет то, что в тот момент я была знакома с этим паттерном в теории, но ещё не использовала его на практике.

Как же его... как он называется? Погуглить паттерн для отправки в Кафку с отдельной таблицей?

Transactional Outbox! — выпаливаю я.

— Точно! — подхватывает коллега. — Мы как раз его на прошлом проекте использовали, подойдет для нашей ситуации.


Фууух, ура!

Потом я конечно поняла, что лид совсем не обязан всё знать и не нужно так переживать, но это уже совсем другая история 😉


Кратко, в чем идея паттерна Transactional Outbox?

У нас есть бизнес-таблица (например, orders) и отдельная таблица outbox.

➡️ В одной транзакции мы пишем данные и в таблицу orders, и в outbox. Записав, комитим транзакцию.

➡️ Отдельный процесс (например, джоба по расписанию или change data capture) читает outbox и отправляет сообщение в брокер.

➡️ После успешной отправки сообщение помечается как обработанное (может потом удаляться).

Таким образом, если при сохранении данных что-то пойдет не так, и транзакция откатится, то эти данные никак в брокер не попадут.

Если же мы всё сохраним, а потом приложение упадет, не успев отправить данные — ничего страшного 😊 Всё, что нужно отправить, будет дожидаться в таблице outbox. Отправим после восстановления.

Таблица outbox может содержать как уже готовое к отправке сообщение "payload", так и набор полей, а также поле со статусом.

Паттерн применим не только при создании записей, но и при изменении/удалении, если об этом нужно отправлять событие.

Реализация паттерна даёт at-least-once доставку, то есть сообщение не потеряется, но возможны дубликаты.

С тех пор мы успешно используем Transactional Outbox на проектах.

🤔 А зачем отдельная таблица? Можно же сделать поле со статусом в таблице orders: NEW, PROCESSED. И пусть фоновый процесс берет данные из самой orders и меняет статус после отправки.

Да, так можно сделать, это проще. Но у такого подхода есть минусы:

➖ мы смешаем бизнес-логику (данные orders) с логикой интеграции: статус отправки, timestamp отправки, другая служебная информация, которая не нужна в orders. Отдельная таблица outbox дает больше гибкости.

outbox-таблицу можно чистить (сразу или спустя время), а добавленные в orders статус (дата и др.) отправки останутся там

✏️ Паттерн Transactional Outbox решает так называемую dual-write problem — как записать данные в базу и одновременно отправить событие наружу так, чтобы они не разъехались. С ним мы можем гарантировать, что сообщение будет отправлено после успешного выполнения транзакции в базе данных и не потеряется. Cхема в комментах.

_______
Сталкивались ли вы с Transactional Outbox на практике? Делали по классике или через статусы отправки в основной таблице?
  • 👍 79
  • 🔥 44
  • ❤ 17
  • ❤‍🔥 5
  • 💯 1
More from @jane_yanchenko
  1. Sep 21, 2026🔗 Подборка постов про Кафку Как обещала на стриме, собрала посты про Кафку в удобное огла…
  2. Sep 21, 2026🎞 Готова запись стрима про Кафку: https://youtu.be/2aRKsD-MWDA Большое спасибо всем, кто…
  3. Sep 16, 2026Сегодня стрим по Кафке в 19:00 Планируем не в формате доклада, а в формате вопрос-ответ, ч…
  4. Sep 16, 2026Post #413
  5. Sep 16, 2026Post #412
  6. Sep 16, 2026Post #411
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →