PRO

Как гарантировать at-least-once или exactly-once доставку сообщений?

Доставка at-least-once означает, что сообщение будет обработано хотя бы один раз, но возможны дубликаты. Exactly-once означает, что итоговый эффект обработки возникает один раз; в распределённых системах это обычно достигается не одной настройкой брокера, а идемпотентными получателями, уникальными идентификаторами, транзакциями и контролем фиксации результата.
Подробный ответ

At-most-once, at-least-once и exactly-once

СемантикаЧто гарантируетОсновной риск
At-most-onceСообщение обработается не более одного разаСообщение может потеряться
At-least-onceСообщение будет доставлено хотя бы разВозможна повторная обработка
Exactly-onceИтоговый эффект операции возникает один разСложно обеспечить между независимыми системами

Как получить at-least-once

Получатель подтверждает обработку только после успешного выполнения бизнес-операции. Если получатель упал до подтверждения, брокер повторно доставит сообщение другому экземпляру. Так риск потери снижается, но появляется риск дубликата.

1. Получатель получает сообщение
2. Выполняет бизнес-операцию
3. Сохраняет результат
4. Подтверждает обработку брокеру

Если сбой произошёл до шага 4,
сообщение может быть доставлено повторно.

Почему exactly-once сложно

Представим задачу: списать деньги во внешнем платёжном сервисе, сохранить заказ в базе и подтвердить сообщение брокеру. Если процесс упадёт между этими шагами, нельзя одним обычным действием атомарно гарантировать результат во всех независимых системах.

Практический путь к exactly-once effect

  • каждому сообщению назначают уникальный идентификатор;

  • получатель хранит факт обработки идентификатора в базе данных;

  • бизнес-эффект и запись об обработке выполняют в одной локальной транзакции;

  • повторное сообщение с тем же идентификатором не создаёт новый эффект;

  • для внешних API передают идемпотентный ключ, если сервис его поддерживает.

processed_messages:
  message_id: string, unique
  processed_at: timestamp

business_operation:
  operation_id: string, unique
  status: completed

Outbox pattern

Чтобы не потерять событие после изменения данных, бизнес-изменение и запись исходящего события сохраняют в одной транзакции базы. Отдельный процесс читает таблицу исходящих событий и публикует их в брокер. Это называется outbox pattern.

Как ответить на собеседовании

Для at-least-once подтверждаю сообщение только после успешной обработки, поэтому допускаю дубликаты. Для exactly-once effect делаю получателя идемпотентным: использую message ID, уникальное ограничение и одну транзакцию для записи результата и отметки обработки. Между несколькими независимыми системами exactly-once редко обеспечивается одной настройкой, поэтому нужны идемпотентность, outbox и идемпотентные ключи внешних вызовов.

Оцени свой прогресс

Честно оцени своё понимание этого вопроса, чтобы мы могли построить твой учебный трек максимально эффективно.
Читать в блоге