Модель RabbitMQ: exchange → queue
В RabbitMQ продюсер пишет НЕ напрямую в очередь, а в EXCHANGE с routing key. Exchange по bindings распределяет сообщение по очередям. Это ключевое отличие от Kafka, где продюсер пишет в топик-партицию напрямую.
Типы exchange: direct (точное совпадение routing key с binding), topic (шаблоны с точкой и подстановками * и #), fanout (рассылка во все привязанные очереди — pub/sub), headers (маршрутизация по заголовкам). Так одной моделью покрываются и точечная доставка, и широковещание, и фильтрация.

Ack/nack и publisher confirms
Consumer подтверждает обработку через basicAck. При basicNack/basicReject сообщение либо возвращается в очередь (requeue=true), либо отправляется в DLQ через DLX (requeue=false). Manual ack — стандарт для прода; auto ack коммитит до обработки и опасен потерями.
С другой стороны цепочки — publisher confirms: брокер асинхронно подтверждает producer'у приём сообщения в exchange. Без confirms producer не знает, дошло ли сообщение до брокера. Это аналог acks=all в Kafka для надёжной отправки.
Prefetch (QoS)
Prefetch (channel.basicQos(N)) ограничивает количество неподтверждённых сообщений, выданных consumer'у одновременно. Это защищает медленный обработчик от переполнения памяти и обеспечивает FAIRNESS: быстрый consumer не выгребает всё, оставляя медленным пустой канал.
Слишком большой prefetch теряет fairness и увеличивает latency «забронированных, но не обработанных» сообщений (они стоят в локальной очереди consumer'а, пока тот переваривает предыдущие). Типичные значения — десятки сообщений, точное значение подбирают по нагрузке.
DLQ через DLX
Dead-lettering в RabbitMQ настраивается на уровне очереди через аргументы: x-dead-letter-exchange (куда переслать) и опционально x-dead-letter-routing-key. В DLQ автоматически уходят сообщения по трём причинам: rejected без requeue, истёк TTL сообщения, превышен max-length очереди.
В DLQ сохраняются заголовки с причиной (x-death) — это позволяет дальше разобрать поток ошибок. Без алертинга и владельца DLQ — это просто скрытая потеря сообщений (см. урок DLQ/retries).
Отложенные сообщения
Из коробки RabbitMQ не умеет «отправить через N минут». Два подхода: установить плагин rabbitmq_delayed_message_exchange (готовый «delayed exchange») — самый простой путь.
Альтернатива — паттерн TTL + DLX: сообщение шлют в очередь БЕЗ consumer'а с x-message-ttl=N, после истечения сообщение переезжает через DLX в боевую очередь. Менее очевидно, но работает без плагинов.
SQS: Standard vs FIFO
SQS — managed-очередь AWS, без exchange'ей: продюсер шлёт прямо в очередь. Standard-очередь — at-least-once с возможным переупорядочиванием и near-infinite throughput. FIFO-очередь даёт строгий порядок и exactly-once-обработку на уровне SQS (через MessageGroupId для порядка и MessageDeduplicationId для дедупликации в 5-минутном окне) ценой ограниченного throughput.
Ключевое понятие — visibility timeout: после ReceiveMessage сообщение НЕ удаляется, а становится невидимым на N секунд. Если consumer не удалит его за это время (DeleteMessage), оно снова станет видимым — отсюда at-least-once и требование идемпотентности. Для отложки используют DelaySeconds на сообщении/очереди.
Как отвечать на собеседовании
Главное отличие RabbitMQ от Kafka — модель: продюсер пишет в EXCHANGE, тот по bindings разбрасывает в очереди (типы exchange direct/topic/fanout/headers). Объясните manual ack/nack и publisher confirms как аналог acks=all. Подчеркните роль prefetch (fairness + защита памяти) и DLQ через DLX (с причинами в x-death). Для SQS различите Standard (at-least-once) и FIFO (MessageGroupId/DeduplicationId), и опишите visibility timeout как механизм at-least-once: не удалил вовремя → сообщение вернулось.