---
title: 'Порівняння черг повідомлень: Redis, RabbitMQ, Kafka | DevSense'
description: "Як вибрати брокер для асинхронної роботи: порівняння черг в пам'яті (Redis), AMQP-брокерів (RabbitMQ) та журналів коммітів (Kafka) за критеріями впорядкованості, масштабу, надійності та вартості експлуатації."
faq:
    - { question: 'В чому ключова відмінність класичної черги (наприклад, RabbitMQ) від лог-орієнтованого брокера (наприклад, Kafka)?', answer: 'RabbitMQ працює за моделлю «розумний брокер, дурний споживач»: брокер сам стежить за тим, хто прочитав повідомлення, чи підтвердив його, і видаляє дані відразу після успішної обробки. Kafka використовує модель «дурний брокер, розумний споживач»: повідомлення послідовно записуються в лог на диску і зберігаються заданий час. Споживачі самі керують своїм покажчиком читання (offset), що дозволяє їм перечитувати історію незалежно.' }
    - { question: 'Чому для черг задач не рекомендують використовувати звичайні таблиці в реляційних базах даних?', answer: "Реляційні БД не оптимізовані під патерн черг. Постійне опитування (polling) таблиць створює блокування рядків, високе навантаження на CPU і призводить до фрагментації даних (bloat) через лавиноподібні вставки та видалення. Брокери черг зберігають стан в оперативній пам'яті (або оптимізованих послідовних файлах на диску) і використовують push-повідомлення для воркерів, забезпечуючи високу пропускну здатність." }
    - { question: 'Завдяки чому Apache Kafka забезпечує екстремально високу пропускну здатність?', answer: 'Kafka пише повідомлення строго послідовно в лог на диску, активно використовуючи системний кеш сторінок ОС та механізм zero-copy (передача даних у мережевий сокет в обхід юзерспейсу). Вона розділяє топіки на партиції для паралельної роботи кількох брокерів і групує повідомлення в пакети (batching) для зниження мережевого оверхеду.' }
    - { question: 'Коли Redis є хорошим вибором для роботи з чергами, і в чому його обмеження?', answer: "Redis — відмінний вибір з мікросекундною затримкою для простих черг (через Lists) або структурованих потоків (Streams), якщо ви вже використовуєте його в проекті для кешу. Однак він обмежений об'ємом оперативної пам'яті сервера (оскільки всі активні дані лежать в RAM) і позбавлений складного роутингу, DLX (черг недоставлених листів) та гарантованого довгострокового збереження на диску." }
published: '2026-05-31'
---
# Порівняння черг повідомлень: Redis, RabbitMQ та Apache Kafka

Рішення винести важкі завдання із синхронного HTTP-запиту — важливий крок в архітектурі будь-якого проекту. Але вибір **інструменту** для цього завдання часто призводить до ступору. Вам не потрібно розгортати кластер Kafka з трьох нод, щоб надсилати 50 листів привітання на день, так само як не варто будувати фінансову книгу транзакцій на базі Redis Pub/Sub. Ідеальний брокер вибирається на основі **вимог до впорядкованості**, **гарантій доставки**, **пропускної здатності** та того, **який оверхед на адміністрування готова нести ваша команда**.

**Пов’язані матеріали:** [Збір подій під високим навантаженням](high-load-event-ingestion) · [Бази даних під навантаженням](database-performance-and-scaling) · [Спостережуваність і моніторинг](observability-monitoring-laravel)

## Зміст

* [Чому не варто використовувати звичайну таблицю в БД?](#why-not-db)
* [Три архітектурні моделі роботи з повідомленнями](#three-models)
* [Redis: простий, швидкий, в оперативній пам'яті](#redis)
* [RabbitMQ: розумний брокер, гнучка маршрутизація](#rabbitmq)
* [Apache Kafka: розподілений журнал коммітів](#kafka)
* [Порівняльна таблиця можливостей](#matrix)
* [Гарантії доставки: At-least-once, At-most-once, Exactly-once](#delivery)
* [Порядок повідомлень, групи споживачів та масштабування](#ordering)
* [Вартість експлуатації: Managed vs Self-hosted](#ops-cost)
* [Часті помилки](#common-mistakes)
* [Чеклист](#checklist)
* [Квіз для самоперевірки](#self-test-quiz)

---

<a id="why-not-db"></a>
## Чому не варто використовувати звичайну таблицю в БД?

Ідея записувати завдання в таблицю `jobs` в PostgreSQL або MySQL, індексувати колонку `status` і опитувати її щосекунди виглядає дуже привабливо.
Для невеликих проектів це **дійсно працює**. Але зі зростанням навантаження реляційна БД починає здавати позиції:
* **Роздування таблиць (Table bloat)** — СУБД погано справляються з постійним циклом швидкого запису та подальшого видалення рядків. Накопичуються «мертві рядки» (dead tuples), падає швидкість індексів, СУБД витрачає ресурси на очищення.
* **Блокування при конкурентному опитуванні** — коли кілька воркерів одночасно виконують `SELECT ... FOR UPDATE LIMIT 1`, вони починають конкурувати за блокування одних і тих самих сторінок індексу, що паралізує продуктивність.
* **Push проти Pull** — БД змушує вас постійно опитувати її (pull), тоді як брокери черг відправляють повідомлення у відкриті TCP-сесії воркерів миттєво (push).

---

<a id="three-models"></a>
## Три архітектурні моделі роботи з повідомленнями

1. **Тимчасова черга в пам'яті (Redis Lists / Pub/Sub)** — швидка, легка, дані обмежені RAM, для простих сценаріїв.
2. **Класична черга повідомлень (RabbitMQ / ActiveMQ)** — складна маршрутизація, брокер зберігає стан черг, повідомлення видаляються відразу після підтвердження обробки.
3. **Журнал подій (Kafka / Redpanda)** — незмінний лог на диску, куди повідомлення тільки дописуються. Вони не видаляються після читання, а споживачі самі зберігають свої покажчики (offsets).

---

<a id="redis"></a>
## Redis: простий, швидкий, в оперативній пам'яті

Redis — це високопродуктивне сховище даних в пам'яті, яке також пропонує примітиви для роботи з чергами.

### Механізми
* **Списки (`LPUSH` / `BRPOP`)** — базова FIFO-черга. Дуже проста в налаштуванні, мікросекундні затримки, але немає складного роутингу.
* **Потоки (Redis Streams, починаючи з 5.0)** — лог подій на запис з підтримкою груп споживачів та підтвердження доставки (`XACK`).
* **Pub/Sub** — патерн «видавець-передплатник» без збереження стану. Якщо в момент відправки повідомлення воркер був відключений, повідомлення **втрачається назавжди**.

### Сильні сторони
* Не вимагає додаткової інфраструктури, якщо Redis вже використовується в проекті для кешу або сесій.
* Мінімальні затримки при обробці.

### Слабые стороны
* **Обмеження RAM** — якщо воркери зависнуть, а черга продовжить рости, ви швидко вичерпаєте оперативну пам'ять сервера.
* **Надійність зберігання** — синхронізація на диск (AOF/RDB) відбувається асинхронно, при раптовому збої живлення частина повідомлень може зникнути.

---

<a id="rabbitmq"></a>
## RabbitMQ: розумний брокер, гнучка маршрутизація

RabbitMQ — класичний брокер повідомлень на базі протоколу AMQP, написаний на Erlang.

### Ключові концепты
* **Producers** (видавці) відправляють повідомлення в точки обміну (**Exchanges**).
* **Exchanges** маршрутизують повідомлення в черги (**Queues**) на основі правил зв'язування (**Bindings**) — за ключами роутингу, заголовками або правилом fanout (мовлення всім).
* **Consumers** (споживачі) забирають повідомлення з черг.

```
Producer ──> [ Exchange ] ──(Правила роутингу)──> [ Queue ] ──> Consumer
```

### Сильні сторони
* Складні патерни маршрутизації (наприклад, відправка повідомлень за маскою топіка).
* Підтвердження (Ack/Nack) для кожного окремого повідомлення.
* Вбудований механізм черг недоставлених листів (Dead Letter Exchanges) для обробки помилок.

### Слабкі сторони
* Вимагає розуміння специфіки рантайму Erlang для конфігурації та кластеризації.
* Продуктивність черг падає, якщо вони розростаються до мільйонів повідомлень і скидаються на диск.

---

<a id="kafka"></a>
## Apache Kafka: розподілений журнал коммітів

Kafka — це не класична черга. Це розподілений, партиційований, append-only журнал транзакцій.

### Ключові концепты
* **Топіки (Topics)** діляться на розділи (**Partitions**).
* Повідомлення записуються на диск строго послідовно.
* Кожне повідомлення ідентифікується його зміщенням (**Offset**).
* Споживачі об'єднуються в групи (**Consumer Groups**); Kafka закріплює партиції за учасниками групи.

```
Топік: Orders
Партиція 0: [Повідомлення 0][Повідомлення 1][Повідомлення 2] <-- Споживач А (Offset 2)
Партиція 1: [Повідомлення 0][Повідомлення 1]               <-- Споживач Б (Offset 1)
```

### Сильні сторони
* **Екстремальна продуктивність** — запис йде послідовно на диск, читання використовує системний кеш сторінок ОС.
* **Перегравання історії (Replay)** — оскільки повідомлення не видаляються після читання, ви завжди можете скинути offset назад і прочитати історію заново.
* **Масштабованість** — партиціювання дозволяє горизонтально масштабувати читання та запис на безліч серверів.

### Слабкі сторони
* Висока складність розгортання та підтримки. Вимагає ZooKeeper або KRaft для координації кластера.
* Відносно високі затримки (мілісекунди) порівняно з Redis.
* Надлишкова для простих фонових завдань.

---

<a id="matrix"></a>
## Порівняльна таблиця можливостей

| Характеристика | Redis (Lists) | RabbitMQ | Apache Kafka |
|---------|---------------|----------|--------------|
| **Основна модель** | Список / Потік в RAM | Розумний брокер (AMQP) | Розподілений журнал коммітів |
| **Зберігання даних** | Оперативна пам'ять / Диск | Диск / Пам'ять (налаштовується) | Завжди диск (журнал коммітів) |
| **Макс. пропускна здатність**| Висока (обмежена CPU ядра/RAM) | Середня (десятки тисяч в сек) | Екстремальна (мільйони в сек через партиції) |
| **Життєвий цикл повідомлення** | Видаляється при читанні | Видаляється після Ack | Зберігається згідно з Retention policy |
| **Гнучкість роутингу** | Відсутня (FIFO) | Дуже висока (Exchanges) | Маршрутизація за ключем партиції |
| **Гарантія порядку** | Строго в межах списку | Строго в межах черги (при 1 воркері) | Строго **в межах партиції** |

---

<a id="delivery"></a>
## Гарантії доставки

Жодна розподілена система не може гарантувати доставку «рівно один раз» (Exactly-once) без істотного падіння продуктивності через двофазні комміти.

* **At-most-once** (максимум один раз) — повідомлення надсилається без підтвердження. При збої мережі або падінні воркера повідомлення втрачається.
* **At-least-once** (мінімум один раз) — воркер зобов'язаний підтвердити обробку. Якщо він впав посеред процесу, брокер надішле повідомлення заново. **Логіка застосунку зобов'язана бути ідемпотентною**.
* **Exactly-once** (рівно один раз) — вимагає складної координації (транзакції в Kafka). На практиці найчастіше реалізується через схему At-least-once + дедуплікація на стороні одержувача.

> [!NOTE]
> **Золоте правило ідемпотентності**
> Завжди проектуйте обробники черг так, щоб вони могли коректно обробляти дублікати повідомлень без псування даних. Використовуйте унікальні ID транзакцій або бізнес-ключі.

---

<a id="ordering"></a>
## Порядок повідомлень, групи споживачів та масштабування

* **RabbitMQ** гарантує порядок тільки всередині однієї черги. Якщо ви запустите кілька паралельних воркерів на одну чергу, вони оброблятимуть повідомлення з різною швидкістю, що призведе до порушення порядку виконання бізнес-логіки.
* **Kafka** гарантує порядок **строго в межах однієї партиції**. Щоб повідомлення щодо конкретного замовлення оброблялися строго за порядком, надсилайте їх з ключем партиціювання (наприклад, `order_id`).

---

<a id="ops-cost"></a>
## Вартість експлуатації: Managed vs Self-hosted

* **Redis** простий в адмініструванні. У будь-якого хмарного провайдера є готовий керований Redis.
* **RabbitMQ** вимагає моніторингу пам'яті, диска та стану синхронізації Erlang-кластера. Хмарні SaaS (CloudAMQP) значно спрощують життя.
* **Kafka** — найдорожчий і складний в експлуатації інструмент. Управління партиціями, ребалансування, конфігурація брокерів та KRaft вимагають виділеної команди інженерів. Рекомендується використовувати managed-рішення (Confluent, AWS MSK, Aiven), якщо у вас немає свого штату DevOps.

---

<a id="common-mistakes"></a>
## Часті помилки

1. **Відправка повідомлень всередині транзакції БД**: Публікація завдання в чергу до того, як транзакція бази даних закоммічена. Якщо воркер спрацює швидше за комміт, він не знайде потрібні записи в БД.
2. **Відсутність ліміту prefetch в RabbitMQ**: Без налаштування prefetch RabbitMQ вишле всі повідомлення черги першому вільному воркеру, перевантаживши його, поки решта простоюватимуть.
3. **Використання Kafka без ключів партиціювання**: Відправка повідомлень без вказівки ключа роутингу, через що події розподіляються випадково і порушується порядок їх обробки.
4. **Ставлення до Pub/Sub як до персистентної черги**: Використання Redis Pub/Sub для критичних фонових завдань у надії, що повідомлення десь буферизуються.

---

<a id="checklist"></a>
## Чеклист

1. **Оцініть обсяг:** Менше 10 000 повідомлень на секунду? Забудьте про Kafka, почніть з Redis або RabbitMQ.
2. **Визначте вимоги до надійності:** Чи допустима втрата повідомлень при падінні сервера? Якщо ні, чисті списки Redis в RAM не підійдуть.
3. **Чи потрібен складний роутинг:** Чи потрібна маршрутизація за темами, заголовками або правилами? Вибирайте RabbitMQ.
4. **Чи важливий суворий порядок:** Чи потрібно зберігати суворий порядок подій щодо конкретного об'єкта при паралельній обробці? Вибирайте Kafka з ключами партиціювання.
5. **Оцініть ресурси команди:** Чи є у вас інженери для підтримки ZooKeeper/KRaft? Якщо ні, використовуйте хмарні managed-сервіси.

---

## Підсумок

Правильний вибір інструменту залежить від характеру ваших даних. Використовуйте **Redis** для швидких і простих завдань, **RabbitMQ** при складній логіці маршрутизації та **Kafka** для побудови масштабованих розподілених журналів подій.

---

<a id="self-test-quiz"></a>
## Квіз для самоперевірки

### Запитання 1: Що відбувається з повідомленням в Redis Pub/Sub, якщо в момент публікації на каналі немає жодного активного підписника?
- А) Воно зберігається в черзі в пам'яті до появи першого підписника.
- Б) Воно відкидається і втрачається назавжди.
- В) Воно автоматично записується в RDB-файл на диску.

<details>
<summary>Показати правильну відповідь</summary>

**Правильна відповідь: Б**
Redis Pub/Sub працює за принципом «вистрілив і забув». Він не буферизує повідомлення для відключених клієнтів. Якщо підписників немає, повідомлення знищується.
</details>

### Запитання 2: Як в Apache Kafka гарантувати, що всі події щодо зміни статусу конкретного користувача будуть оброблені строго в тому порядку, в якому вони відбулися?
- А) Використовувати тільки одну ноду брокера.
- Б) Використовувати ID користувача (`user_id`) як ключ партиціювання (partition key).
- В) Встановити ліміт зберігання логів у нескінченність.

<details>
<summary>Показати правильну відповідь</summary>

**Правильна відповідь: Б**
Kafka гарантує суворий порядок повідомлень тільки всередині однієї партиції. Використання `user_id` як ключа гарантує, що всі події цього користувача потраплять в один і той самий розділ, зберігши хронологію обробки.
</details>