Раздел 37 · Redis с нуля

Pub/Sub: рассылка событий в реальном времени

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

До сих пор Redis хранил данные: строки, списки, кэш. В прошлом уроке мы закончили защищать кэш. Теперь новая роль: Redis как почтальон между частями приложения. Покупатель оформил заказ, и об этом должны узнать сразу несколько сервисов: отправка писем, склад, панель менеджера. Для такой рассылки в Redis есть Pub/Sub.

Радио

Представь радиостанцию. Ведущий говорит в микрофон и не знает, кто его слушает: сто человек, тысяча или никто. Слушатель настраивает приёмник на частоту и слышит всё, что звучит в эфире, пока приёмник включён. Если ты включил радио в 9:05, новости в 9:00 ты пропустил, записи эфира нет.

Pub/Sub в Redis работает так же. Издатель отправляет сообщение в канал, Redis тут же раздаёт копии всем, кто сейчас подписан. Издатель ничего не знает о подписчиках, подписчики ничего не знают об издателе.

Подписаться и опубликовать

Нужны два терминала. В первом сервис писем подписывается на канал orders:new:

127.0.0.1:6379> SUBSCRIBE orders:new
1) "subscribe"
2) "orders:new"
3) (integer) 1
Reading messages... (press Ctrl-C to quit or any key to type command)

Redis подтвердил подписку тремя строками: что сделано, на какой канал и на сколько каналов этот клиент теперь подписан. Дальше redis-cli ждёт сообщений. Соединение перешло в режим подписчика: обычные команды вроде GET в нём не работают, только команды подписки и PING.

Во втором терминале магазин публикует событие командой PUBLISH:

127.0.0.1:6379> PUBLISH orders:new order:16
(integer) 1

Ответ 1 значит «сообщение получил один подписчик». А в первом терминале появилось:

1) "message"
2) "orders:new"
3) "order:16"

Тип события, канал и само сообщение. Сообщение это обычная строка, часто в неё кладут JSON с подробностями заказа.

Нет слушателя, нет сообщения

Опубликуем в канал, где никого нет:

127.0.0.1:6379> PUBLISH orders:paid order:16
(integer) 0

Ноль получателей, и сообщение исчезло. Redis его нигде не сохранил. Если подписчик подключится через секунду, этого сообщения он не увидит. Такую доставку называют «отправил и забыл».

Отсюда ограничения, которые важно запомнить:

  • сервис писем перезапускался 10 секунд, и все заказы за это время он пропустил;
  • подписчик упал посреди обработки, повторно сообщение не придёт;
  • медленный подписчик, который не успевает читать, Redis в итоге отключит, чтобы не копить его сообщения в памяти.

Поэтому Pub/Sub хорош для событий, которые не жалко потерять: «обнови страницу», «у товара сменилась цена, перерисуй», уведомление в чат поддержки, сброс локального кэша на всех серверах. Если каждое сообщение важно, нужна очередь, которая хранит сообщения. О ней следующий урок.

урок из курса

Урок из курса «Redis с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.