Компьютерные сети

Message Queues: Kafka, RabbitMQ

LinkedIn обрабатывает 7 триллионов сообщений в день через Kafka. Как справиться с такой нагрузкой, если каждый запрос ждёт ответа? Ответ - не ждать.

  • **Netflix** использует Kafka для real-time персонализации: каждый клик, пауза, перемотка - событие в очередь. 8 миллионов событий в секунду.
  • **Uber** через Kafka связывает 4000+ микросервисов. Заказ такси генерирует сотни событий: matching, pricing, ETA, payments - всё асинхронно.
  • **Slack** использует RabbitMQ для задач: отправка уведомлений, обработка файлов, поиск. Пиковые нагрузки (Monday 9 AM) сглаживаются очередью.

Предварительные знания

  • Networking in Distributed Systems

Message Queues

**Message Queue** - это посредник между сервисами, который хранит сообщения до тех пор, пока получатель не будет готов их обработать. Вместо синхронного вызова (жди ответа) отправитель кладёт сообщение в очередь и продолжает работу.

Это как **почтовый ящик**: отправитель бросает письмо и уходит, а получатель забирает когда удобно. Producer и Consumer работают независимо - они даже могут быть написаны на разных языках.

**Главное преимущество** - decoupling (развязка). Producer не знает кто и когда обработает сообщение. Это даёт: масштабируемость (добавляй consumers), отказоустойчивость (очередь переживёт падение consumer), выравнивание нагрузки (пики сглаживаются).

Базовые гарантии очереди: сообщение будет доставлено (если очередь persistent), порядок сохраняется (обычно FIFO), одно сообщение - один consumer (в модели queue). Но дьявол в деталях - разные системы дают разные гарантии.

Почему message queue лучше прямого HTTP вызова для задачи 'отправить email после регистрации'?

Apache Kafka

**Apache Kafka** - это распределённый event streaming platform. В отличие от классических очередей, Kafka хранит сообщения как **лог** - append-only структуру. Сообщения не удаляются после чтения, а хранятся заданное время (retention).

Ключевые абстракции: **Topic** - категория сообщений (как таблица в БД). **Partition** - единица параллелизма внутри топика (как шард). **Consumer Group** - группа consumers которые делят работу над partition'ами.

**Kafka vs классическая очередь**: в RabbitMQ сообщение удаляется после ACK. В Kafka сообщение остаётся - можно перечитать, другой consumer group может читать с начала. Это делает Kafka идеальной для event sourcing и реплея событий.

Почему в Kafka сообщения с одинаковым key попадают в одну partition?

RabbitMQ

**RabbitMQ** - классический message broker, реализующий протокол AMQP. В отличие от Kafka, это настоящая очередь: сообщение доставляется одному consumer и удаляется после подтверждения (ACK).

Архитектура RabbitMQ: **Exchange** - точка входа, принимает сообщения от producer. **Queue** - хранит сообщения для consumer. **Binding** - правило маршрутизации от exchange к queue. Exchange типы: direct, fanout, topic, headers.

**Kafka vs RabbitMQ**: Kafka - для high-throughput event streaming (логи, аналитика, event sourcing). RabbitMQ - для task queues и сложной маршрутизации (email, notifications, workflows). Kafka хранит историю, RabbitMQ удаляет после ACK.

Какой exchange type использовать для отправки уведомлений с routing по severity (error, warn, info)?

Pub/Sub Pattern

**Publish-Subscribe** - паттерн где publisher не знает о subscribers. Сообщение публикуется в topic/channel, а все подписчики получают копию. В отличие от queue (один получатель), в pub/sub сообщение идёт всем.

Pub/Sub отлично подходит для событий: 'пользователь зарегистрировался' → слушают: email-сервис (отправить welcome), analytics (записать метрику), recommendations (создать профиль). Каждый делает своё дело независимо.

**Реализации Pub/Sub**: Redis Pub/Sub (простой, без persistence), Google Cloud Pub/Sub (managed, at-least-once), Kafka consumer groups (каждая группа - отдельный subscriber), RabbitMQ fanout exchange.

В чём главный риск Redis Pub/Sub для критичных событий?

Delivery Semantics

**Delivery Semantics** - гарантии доставки сообщений. Три уровня: **At-most-once** (не более одного раза - может потеряться), **At-least-once** (хотя бы раз - может дублироваться), **Exactly-once** (ровно один раз - святой Грааль).

**Exactly-once в реальности**: почти всегда это 'effectively-once' - at-least-once + idempotent consumer. Kafka Transactions дают exactly-once для read-process-write внутри Kafka, но если consumer пишет во внешнюю БД - нужна idempotency.

**Правило**: если сомневаешься - выбирай at-least-once + idempotency. Потеря данных (at-most-once) обычно хуже дубликатов. А exactly-once либо невозможен, либо слишком дорог для большинства случаев.

Exactly-once доставка всегда возможна, просто нужен правильный брокер

True exactly-once между системами невозможен из-за Two Generals Problem. Реально достижимо: at-least-once + idempotent processing

Сеть ненадёжна. Если consumer обработал сообщение и упал до отправки ACK - broker пошлёт снова. Consumer не может отличить 'первый раз' от 'retry'. Поэтому idempotency - обязанность consumer, а не брокера.

Как обеспечить exactly-once семантику при записи из Kafka в PostgreSQL?

Итоги

  • **Message Queue** развязывает producer и consumer - асинхронная обработка, масштабируемость, отказоустойчивость
  • **Kafka** - distributed log для event streaming. Хранит историю, поддерживает replay, partition = единица параллелизма
  • **RabbitMQ** - классический broker для task queues. Exchange→Queue→Consumer, сообщение удаляется после ACK
  • **Pub/Sub** - broadcast одного сообщения всем подписчикам. Отлично для событий (user registered → email + analytics + recommendations)
  • **Delivery semantics**: at-most-once (может потеряться), at-least-once (может дублироваться), exactly-once (idempotent consumer)

Связанные темы

Message Queues - центральная нервная система распределённых систем:

  • Распределённые системы — Очереди решают проблемы partial failures и latency через асинхронность
  • RPC и gRPC — Синхронный vs асинхронный - выбор архитектуры. Часто используются вместе

Вопросы для размышления

  • Какие операции в вашем приложении можно сделать асинхронными через очередь? (отправка email, генерация отчётов, обработка изображений...)
  • Что случится с вашей системой если consumer упадёт на час? Сообщения накопятся или потеряются?
  • Как бы вы реализовали idempotency для операции 'списать деньги со счёта'?

Связанные уроки

  • bt-13-kafka
Message Queues: Kafka, RabbitMQ

0

1

Войти