Sobes.tech
Назад к вопросам
Middle+
6

Как гарантировать атомарность записи в базу данных и отправки события в Kafka (паттерн Transactional Outbox)?

Компании, где спрашивали
луция

Ответ от нейросети

sobes.tech AI

Паттерн Transactional Outbox решает проблему гарантированной доставки событий в Kafka вместе с атомарной записью данных в базу. Основная идея — не отправлять событие напрямую в Kafka в рамках транзакции, а записывать его в специальную таблицу "outbox" в той же транзакции, что и бизнес-данные.

Как это работает:

  1. В рамках одной транзакции базы данных записываем бизнес-данные и добавляем запись в таблицу outbox с событием.
  2. После успешного коммита транзакции отдельный процесс (например, отдельный сервис или background job) читает новые записи из outbox и отправляет их в Kafka.
  3. После успешной отправки событие помечается как отправленное или удаляется из outbox.

Так достигается атомарность: либо данные и событие записаны вместе, либо ничего не записано. Отправка в Kafka происходит асинхронно, но гарантируется, что событие не потеряется.

Пример на Java с использованием Spring и JPA:

@Entity
public class OutboxEvent {
    @Id
    private UUID id;
    private String aggregateType;
    private String aggregateId;
    private String type;
    private String payload;
    private boolean sent;
    // геттеры и сеттеры
}

@Transactional
public void saveBusinessDataAndEvent(BusinessEntity entity, OutboxEvent event) {
    businessRepository.save(entity);
    outboxRepository.save(event);
}

// Отдельный сервис для отправки
public void publishOutboxEvents() {
    List<OutboxEvent> events = outboxRepository.findUnsentEvents();
    for (OutboxEvent event : events) {
        kafkaTemplate.send(event.getType(), event.getPayload());
        event.setSent(true);
        outboxRepository.save(event);
    }
}

Таким образом, мы избегаем проблем с распределёнными транзакциями между базой и Kafka, обеспечивая надежную доставку событий.