При 10 000 WebSocket-з'єднань кожен екземпляр сервера знає лише про своїх клієнтів. Коли потрібно розіслати подію всім (оновлення статусу замовлення, нова транзакція), без єдиного брокера виникає проблема. Ми вирішуємо її за допомогою Redis Pub/Sub: повідомлення публікується в канал, всі активні підписники отримують його. Механізм fire-and-forget із затримкою <1 мс. Брокер не зберігає історію — підходить для коротких сповіщень, інвалідації кешів, синхронізації стану. Нижче — налаштування, інтеграція з Node.js і Laravel, підводні камені.
Коли вибирати Pub/Sub замість Redis Streams?
Pub/Sub вирішує broadcast-задачу: один видавець, кілька підписників, всі отримують однакові повідомлення одночасно. Якщо потрібна гарантована доставка, історія або групи споживачів — використовуйте Redis Streams. Pub/Sub у 2-3 рази швидший за Redis Streams при broadcast-розсилці, але не гарантує доставку. Зведена таблиця:
| Характеристика | Pub/Sub | Redis Streams |
|---|---|---|
| Гарантія доставки | Немає (fire-and-forget) | Так (consumer groups) |
| Зберігання історії | Немає | Так (налаштовуваний TTL) |
| Затримка | < 1 мс | 1-5 мс |
| Підтримка шардування | Тільки sharded Pub/Sub (Redis 7+) | Так (через consumer group) |
| Застосування | Broadcast-сповіщення реального часу | Черги, гарантована обробка |
Як уникнути втрати повідомлень при відключенні підписника?
Прямий спосіб захиститися від втрати повідомлень — дублювати останні події в окремий Redis-ключ з TTL (наприклад, last_event:user:42). Клієнт при підключенні спочатку отримує пропущені події через REST API, потім переходить на Pub/Sub. Для критичних даних (фінансові транзакції) використовуйте Redis Streams з consumer groups. Цей підхід знижує втрати до нуля і економить до 30% ресурсів на повторну обробку.
Базова настройка Redis
Redis з коробки підтримує Pub/Sub. Рекомендовані параметри redis.conf:
# Ліміт пам'яті
maxmemory 512mb
maxmemory-policy allkeys-lru
# Кількість баз
databases 16
# Вимкнути persistence для чистого Pub/Sub
save ""
appendonly no
Для production використовуйте Redis Sentinel або Cluster. Звичайний Pub/Sub в Cluster обмежений шардом — з Redis 7+ використовуйте sharded Pub/Sub (SPUBLISH/SSUBSCRIBE).
Інтеграція з Node.js і Socket.io
Використовуйте бібліотеку ioredis для двох окремих з'єднань (публікатора і підписника). Приклад на TypeScript:
import Redis from 'ioredis';
const publisher = new Redis({ host: 'redis', port: 6379 });
const subscriber = new Redis({ host: 'redis', port: 6379 });
subscriber.subscribe('notifications:user:*', (err, count) => {
if (err) throw err;
console.log(`Subscribed to ${count} channels`);
});
subscriber.on('pmessage', (pattern, channel, message) => {
const userId = channel.split(':')[2];
const payload = JSON.parse(message);
broadcastToUser(userId, payload);
});
async function notifyUser(userId: string, event: object) {
const channel = `notifications:user:${userId}`;
const count = await publisher.publish(channel, JSON.stringify(event));
return count;
}
Для WebSocket використовуйте Socket.io з Redis Adapter:
import { createServer } from 'http';
import { Server } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import { createClient } from 'redis';
const httpServer = createServer();
const io = new Server(httpServer);
const pubClient = createClient({ url: 'redis://redis:6379' });
const subClient = pubClient.duplicate();
await Promise.all([pubClient.connect(), subClient.connect()]);
io.adapter(createAdapter(pubClient, subClient));
httpServer.listen(3000);
Redis Adapter використовує Pub/Sub: при io.to('room').emit() команда публікується в Redis-канал, і всі екземпляри сервера розсилають її клієнтам кімнати.
Інтеграція з Laravel
У Laravel відправка Pub/Sub-повідомлення виглядає так:
use Illuminate\Support\Facades\Redis;
Redis::publish('notifications:user:'.$userId, json_encode([
'type' => 'order.status_changed',
'orderId' => $order->id,
'status' => $order->status,
'timestamp' => now()->toISOString(),
]));
Для прийому повідомлень на клієнті використовуйте Laravel Echo Server або Soketi.
Процес налаштування (покроково)
- Спроектувати схему каналів: зазвичай використовують патерни
entity:action:user_id. - Налаштувати Redis: задати maxmemory, вимкнути AOF для чистого Pub/Sub.
- Реалізувати публікацію подій у бекенді (Node.js, Laravel, Django).
- Підключити WebSocket-сервер (Socket.io, Soketi) з Redis Adapter.
- Розробити механізм fallback-запиту для пропущених подій (через REST).
- Протестувати навантаження: переконатися, що
instantaneous_ops_per_secне перевищує 5 000.
Моніторинг
Використовуйте команди Redis CLI:
redis-cli PUBSUB CHANNELS "*"
redis-cli PUBSUB NUMSUB notifications:user:42
redis-cli PUBSUB NUMPAT
У Prometheus з Redis Exporter відстежуйте instantaneous_ops_per_sec. Зростання вище 5 000 оп/с при навантаженні Pub/Sub — сигнал до оптимізації (зменшити розмір повідомлень, збільшити число каналів).
Чек-лист для production
- Переконайтеся, що Redis працює в режимі Sentinel або Cluster.
- Налаштуйте maxmemory і політику витіснення.
- Використовуйте окремі з'єднання для Pub/Sub (не змішуйте зі звичайними операціями).
- Впровадьте fallback-запити для пропущених повідомлень.
- Обмежте частоту публікацій до 5 000 оп/с на екземпляр.
Обмеження та альтернативи
Втрата повідомлень при реконнекті
Підписник, який відключився на час, не отримує пропущені повідомлення. Для критичних сповіщень — Redis Streams або зберігання останніх подій.
Немає підтвердження доставки
PUBLISH повертає кількість отримувачів, але не гарантує обробку. Для at-least-once — черга (RabbitMQ, Redis Streams).
Навантаження на CPU при великій кількості патернів
PSUBSCRIBE зіставляє кожне повідомлення з усіма патернами. При 10 000+ патернів затримка зростає на 30–50%.
Що входить у роботу
Впровадження Pub/Sub дозволяє знизити витрати на інфраструктуру WebSocket до 40% за рахунок відмови від додаткових брокерів.
- Проектування схеми каналів і патернів під бізнес-логіку.
- Налаштування Redis (конфігурація, кластеризація, моніторинг).
- Інтеграція Pub/Sub з бекендом (Node.js, Laravel, Django — за вашим стеком).
- Підключення WebSocket-сервера (Socket.io, Soketi, Laravel Echo).
- Розробка механізму захисту від втрати повідомлень (fallback-запити).
- Документація з розгортання та експлуатації.
- Передача доступу до репозиторію та інфраструктури.
- Супровід протягом 2 тижнів після здачі.
| Етап | Термін |
|---|---|
| Аналітика та проектування | 1–2 дні |
| Налаштування Redis і Pub/Sub | 1 день |
| Інтеграція з бекендом | 1–2 дні |
| Підключення WebSocket | 1 день |
| Тестування та налагодження | 1–2 дні |
| Разом | від 4 до 6 днів |
Ми працюємо з Redis більше 6 років, реалізували 15+ проектів з Pub/Sub для клієнтів з e-commerce і fintech. Використовуємо production-конфігурації з Sentinel і Cluster, гарантуємо відмовостійкість. Замовте налаштування Redis Pub/Sub для вашого проекту — отримайте консультацію за 1 день. Звертайтеся до нас для впровадження та масштабування.







