Налаштування Redis для Pub/Sub сповіщень

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Налаштування Redis для Pub/Sub сповіщень
Середня
від 1 робочого дня до 3 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Налаштування Redis для Pub/Sub сповіщень

Redis Pub/Sub — це механізм доставки повідомлень у режимі "fire and forget". Брокер не зберігає історію: якщо підписник не слухає в момент публікації, повідомлення втрачається. Це відрізняє його від Redis Streams і робить придатним для коротких real-time сповіщень — оповіщень про події, інвалідації кешу, синхронізації стану між кількома екземплярами сервісу.

Коли використовувати Pub/Sub проти черги

Pub/Sub розв'язує задачу broadcast: один видавець, кілька підписників, всі отримують одне й те саме повідомлення одночасно. Якщо потрібна гарантована доставка, історія повідомлень або групи споживачів — Redis Streams або RabbitMQ.

Типовий випадок для сайту: користувач виконує дію → бекенд публікує подію в канал → WebSocket-сервер отримує подію і рассилає push всім підключеним клієнтам відповідної "кімнати". Без Pub/Sub горизонтальне масштабування WebSocket-серверів неможливе: кожен екземпляр знає лише про свої підключення.

Базова налаштування

Redis підтримує Pub/Sub з коробки без конфігурації. Але варто виставити кілька параметрів у redis.conf:

# Лімітування пам'яті — критично, якщо Redis використовується як кеш
maxmemory 512mb
maxmemory-policy allkeys-lru

# Кількість баз — однієї логічної БД достатньо для prod
databases 16

# Відключити persistence для чистого pub/sub-брокера
save ""
appendonly no

Для production Redis повинен бути в режимі Sentinel або Cluster. Pub/Sub у Cluster має обмеження: повідомлення поширюються лише в межах шарду, якщо не використовувати SPUBLISH/SSUBSCRIBE (Sharded Pub/Sub, Redis 7+).

Реалізація на Node.js з ioredis

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) => {
  // channel = "notifications:user:42"
  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));
  // count — кількість підписників, які отримали повідомлення
  return count;
}

Важливо: publisher і subscriber — різні з'єднання. Після виклику subscribe/psubscribe з'єднання переходить у спеціальний режим і приймає лише команди SUBSCRIBE, UNSUBSCRIBE, PING, RESET, QUIT.

Pattern-matching підписки

PSUBSCRIBE підтримує глоб-шаблони: * (будь-які символи), ? (один символ), [chars] (набір символів). Корисно для підписки на цілий клас каналів:

// Всі события конкретного тенанту
subscriber.psubscribe('tenant:acme:*');

// Конкретний тип события для всіх користувачів
subscriber.psubscribe('*:message:new');

Інтеграція з WebSocket (Socket.io)

Класична схема масштабування 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));

// Тепер io.to('room').emit() працює на всіх екземплярах сервера
httpServer.listen(3000);

Redis Adapter використовує Pub/Sub всередині: при виклику io.to('room').emit() на одному екземплярі команда публікується в Redis-канал, і всі інші екземпляри її отримують і рассилають своїм підключеним клієнтам з цієї кімнати.

Інтеграція з Laravel

Laravel Echo Server або Soketi — стандартний шлях. Але можна прямо через predis або phpredis:

// Публікація события з Laravel
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 Broadcasting з Redis:

// config/broadcasting.php
'connections' => [
    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
        'queue' => '{default}',
        'retry_after' => 90,
    ],
],
# Запуск Laravel Echo Server
npx laravel-echo-server start
# або Soketi (більш сучасна альтернатива)
soketi start --config=soketi.json

Моніторинг

# Перегляд активних Pub/Sub каналів
redis-cli PUBSUB CHANNELS "*"

# Кількість підписників на каналі
redis-cli PUBSUB NUMSUB notifications:user:42

# Pattern-підписки
redis-cli PUBSUB NUMPAT

# Моніторинг всіх команд у реальному часі (обережно на prod)
redis-cli MONITOR

У Redis Exporter для Prometheus метрики Pub/Sub доступні через redis_connected_slaves і спеціальні скрипти. Важлива метрика — instantaneous_ops_per_sec: якщо вона різко зростає при Pub/Sub навантаженні, перевірте розмір повідомлень і частоту публікації.

Обмеження та підводні камені

Втрата повідомлень при реконнекті. Якщо підписник відключився і переподключився, пропущені повідомлення не восстанавливаються. Для критичних сповіщень — Redis Streams з групами споживачів або збереження останніх подій у окремому ключі.

Немає підтвердження доставки. PUBLISH повертає кількість отримувачів, але не гарантує, що вони обробили повідомлення. Для at-least-once доставки потрібна черга.

Навантаження на CPU при великій кількості шаблонів. PSUBSCRIBE зіставляє кожне опубліковане повідомлення зі всіма зареєстрованими шаблонами. При 10,000+ шаблонах це стає помітним.

Терміни

Базова інтеграція Redis Pub/Sub з Socket.io або Soketi на існуючому проекті — 1–2 дні. Повноцінна система сповіщень з персоналізацією каналів, обробкою переподключень і моніторингом — 4–6 днів.