Назад к вопросам
Middle+
6
Как гарантировать атомарность записи в базу данных и отправки события в Kafka (паттерн Transactional Outbox)?
Компании, где спрашивали
луция
Ответ от нейросети
sobes.tech AI
Паттерн Transactional Outbox решает проблему гарантированной доставки событий в Kafka вместе с атомарной записью данных в базу. Основная идея — не отправлять событие напрямую в Kafka в рамках транзакции, а записывать его в специальную таблицу "outbox" в той же транзакции, что и бизнес-данные.
Как это работает:
- В рамках одной транзакции базы данных записываем бизнес-данные и добавляем запись в таблицу outbox с событием.
- После успешного коммита транзакции отдельный процесс (например, отдельный сервис или background job) читает новые записи из outbox и отправляет их в Kafka.
- После успешной отправки событие помечается как отправленное или удаляется из 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, обеспечивая надежную доставку событий.