Заметки бизнес-аналитика
Главная › Системный анализ › Интеграции и REST API

Надёжная асинхронная коммуникация: повторы, дубликаты и dead letter queues

Конспект статьи. Автор оригинала: justwack

Как сделать обработку сообщений надёжной, когда они теряются, дублируются или приходят не по порядку. Надёжность — это не отсутствие повторов, а предсказуемое поведение при каждом сбое.

Где ломается путь сообщения

  • Заказ записан, а событие нет (dual write) — transactional outbox.
  • Неизвестен результат публикации — повтор с тем же ID и идемпотентный потребитель.
  • Повторная доставка — inbox или идемпотентная операция.
  • Бесконечный цикл повторов — задержка, backoff, лимит попыток.
  • «Ядовитое» сообщение — DLQ, диагностика, ручная переотправка после исправления.
  • Порядок и перегрузка — порядок по ключу, prefetch, версии схем, корреляционные ID.

Семантика доставки

Exactly once имеет смысл только в границах одной системы: запись в внешнюю БД или вызов API создают новую границу. Практическая цель — at least once плюс идемпотентный бизнес-эффект.

Outbox и подтверждения

Событие пишется в таблицу outbox в той же транзакции, что и заказ; отдельный процесс публикует его. ID события не меняется при повторах. Ack отправляется только после COMMIT: Ack до коммита создаёт окно потери, после — окно дубля, которое закрывает идемпотентность.

Идемпотентный потребитель

Таблица обработанных сообщений с ключом (потребитель, ID сообщения); вставка ключа и бизнес-изменение — в одной транзакции. Установка статуса идемпотентна сама по себе, а списание суммы или отправка письма — нет.

Какие ошибки повторять

Временные (обрыв соединения, недоступность БД, 429) — повторять. Постоянные (битый JSON, неизвестная схема) — сразу в DLQ. Бизнес-результат (нет товара) — опубликовать как событие. Бюджет повторов: число попыток, максимальный возраст сообщения, задержки, случайный разброс, конечный маршрут.

RabbitMQ

Nack с requeue создаёт горячий цикл, sleep в потребителе держит сообщение и занимает prefetch. Задержки строят на стороне брокера: очереди с TTL без потребителей, после истечения TTL сообщение через dead letter exchange возвращается в основную очередь.

Источник: Надёжная асинхронная коммуникация: повторы, дубликаты и dead letter queues
Автор: justwack
Это конспект, пересказ основных идей. Полный текст, иллюстрации и примеры читайте в оригинальной статье.