PRO

Как работает распределённая очередь сообщений?

Распределённая очередь сообщений отделяет producers от consumers: producer публикует сообщение в broker, а consumer обрабатывает его асинхронно. Для надёжной работы нужны partitions или очереди, replication, acknowledgements, retries, dead-letter queue, идемпотентные обработчики и ясная модель доставки: at-most-once, at-least-once или exactly-once в ограниченном контексте.
Подробный ответ

Зачем нужна очередь

Очередь позволяет не выполнять долгую работу внутри пользовательского HTTP-запроса. Producer публикует событие или задачу, а consumer обрабатывает её независимо: отправляет email, строит feed, генерирует документ, индексирует данные или вызывает внешний сервис.

Основные компоненты

Producer
  |
  v
Broker / Topic / Queue
  |
  +------------------+
  |                  |
Consumer group A   Consumer group B
  |                  |
Email workers      Analytics workers
  • producer создаёт и публикует сообщение;

  • broker принимает, хранит и доставляет сообщения;

  • consumer получает и обрабатывает сообщения;

  • consumer group масштабирует обработку одного потока сообщений между несколькими consumer-ами.

Queue и log-based stream

В классической очереди сообщение обычно удаляется после acknowledgement consumer-а. В log-based broker, например Kafka-подобной модели, сообщения хранятся некоторое время, а consumer хранит offset и может перечитать поток. Конкретная семантика зависит от выбранного broker.

Доставка сообщений

СемантикаСмыслРиск
At-most-onceСообщение доставляется не более одного разаВозможна потеря сообщения
At-least-onceСообщение будет доставлено как минимум один разВозможна повторная обработка
Exactly-onceЭффект обработки проявляется один раз в определённой системеСложно реализовать end-to-end между разными системами

Идемпотентность

В production чаще выбирают at-least-once delivery, поэтому consumer должен быть идемпотентным: повторная обработка одного и того же сообщения не должна создавать двойной платёж, повторный email или дублирующую запись. Для этого используют message ID, deduplication storage, idempotency key и транзакционные паттерны.

Ошибки и retries

При временной ошибке сообщение повторяют с backoff. После ограниченного числа неудачных попыток его отправляют в dead-letter queue для ручного анализа или отдельной обработки. Нельзя бесконечно повторять сообщение, которое всегда падает из-за некорректного формата.

Порядок и partitions

Глобальный порядок во всём распределённом потоке дорог и плохо масштабируется. Обычно порядок гарантируется только внутри partition или для сообщений с одним key, например order ID. Нужно выбирать partition key так, чтобы сохранить нужный порядок и не создать hot partition.

Надёжная публикация

Если запись в БД и публикация события выполняются отдельно, возможна ситуация: данные сохранены, но событие потеряно. Для этого используют transactional outbox pattern: событие сохраняют в той же транзакции, что и бизнес-изменение, а отдельный publisher надёжно передаёт его в broker.

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

Распределённая очередь отделяет producer от consumer и позволяет обрабатывать работу асинхронно и масштабировать consumers. Я проектирую partitions, replication, acknowledgements, retry с backoff и DLQ. Обычно исхожу из at-least-once delivery, поэтому consumer делаю идемпотентным. Для надёжной связи БД и событий использую transactional outbox, а порядок гарантирую только в пределах выбранного partition key.

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

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