Обновить

Комментарии 20

Выглядит немного перегружено... Если уже есть Кафка в виде журнала, то достаточно получить запись в топик order-ов и далее провести по цепочке обработки - с записью в базу, если надо, с передачей в банк и получению ответа. Debezian здесь не видится как необходимая составляющая, но для демонстрации как он функционирует и встраивается в шаблон - сгодится.
IMHO.- debezian более интеграционная составляющая для совмещения двух разных продуктов. Типа есть 2 решения и надо их склеить.

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

зачем kafka, если у вас есть таблица outbox_payments, которая выполняет по сути роль кафки?

Зачем outbox_payments, если есть кафка и можно сразу писать и в таблицу бд и в нужный топик? Дубли из таблицы отсекутся по ключу payment. -1 структура БД и-1 инфраструктурный компонент (Debezium). + прозрачность и надежность обработки.

Спасибо за комментарий.

Проблема что запись в БД и Kafka не синхронизированы между собой. Из-за этого возможны 2 вида проблем:

  1. Произошла запись в Kafka, но при комите транзакции в БД произошла ошибка. В итоге запись Kafka есть, а в БД нет.

  2. Так как Kafka producer не отправляет сообщение сразу, а старается буфферизовать несколько сообщений для большей эффективности передачи данных, то может возникнуть ситуация, что транзакция в БД закомитилась, а сообщение в Kafka Broker так и не было доставлено. В итоге запись в БД есть, а сообщения в Kafka нет

Данный паттерн стремиться решить эти проблемы

Дорого он решает проблемы. Всё верно, транзакции кафки и бд объединить нельзя. Но правильно выставленные коммиты (сначал в БД, потом в кафку) обеспечивают семантику at least once на уровне севриса, т.е. сообщения не теряются, но возможны дубли. А от них можно подстраховаться за счет уникального ключа записи в бд и оработки соответствующего исключения. Исключение будет возникать редко - только когда выключают свет между коммитами в бд и в кафку. Поэтому паттерн интересен с учебной точки зрения, но с практической - сплошной оверхет.

Вы сами приводите пример, когда гарантия at least once не выполняется. Есть категория систем для которых это не позволительно.

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

В случае если в момент времени после коммита транзакции и до записи в Kafka Broker произойдет: OOM Kill producer, падение broker, сетевые проблемы и т.п.

Хороший кейс! При таком сбое оффсет в топике-источнике данных тоже не закоммитится - после восстановления сообщение будет обработано повторно и столкнется со своим близнецом в бд - это ожидаемо и обрабатываемо. Где еще слабые места?

Слабое место, что это работает только в случае, если Kafka является источником сообщений.

Так если она не является источником, то какой смысл в применении обсуждаемого паттерна?

В статье пример, где источник данных - это REST Endpoint по созданию order.

Транспорт bank-service -> order-service так же должен быть организован через outbox для гарантии доставки.
В Вашем же случае если кафка отвалится во время выполнения метода makePaymentByTelephone - то транзакция успешно закоммитится, вызовется лисенер handlePaymentResult который НЕ сможет отправить в кафку и НЕ сможет откатить транзакцию. Т.о. на стороне order-service процесс никогда не перейдёт ни в APPROVED, ни в CANCELLED

Спасибо за комментарий. Да, согласен.

на стороне order-service процесс никогда не перейдёт ни в APPROVED, ни в CANCELLED

Чтобы это исправить достаточно раз в t1 с/м/ч/etc. запускать фоновую задачу, которая просто переводит все PENDING в CANCELLED, если со времени создания прошло t2. Лучше, чтобы t1 < t2.

В таком случае на стороне bank-service деньги будут списаны и платёж будет в approve, а на стороне order service - заказ в cancelled. Разве это не прямое нарушение консистентности?

Какой смысл делать event, я что-то не понял.

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

А иначе получается, что одна часть системы надёжна, а другая - нет

Ну и zookeeper в учебной статье 2026 - вы серьезно?

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации