- Знакомимся с Redis
- Для чего используют Redis
- Как начать работать с Redis
- Основные команды
- Транзакции
- Механизм подписок
- Redis — высокопроизводительное хранилище данных
- Что такое Redis?
- Чем Redis отличается от существующих решений?
- Производительность
- Sharding
- Перспективы развития
- Лицензия и поддерживаемые платформы
- Redis — главное хранилище? Что за хрень?!
- Redis как хранилище данных
- Что нам нужно?
- Что же теперь делать?
- Все данные в памяти. Блин.
- Падения сервера
- Конечный результат
- Стартуем работу с Redis и PHP
- Об этой статье
- Установка Redis
- Установка Redis на Linux
- Установка Redis на Windows
- Подключение к Redis
- Типы данных в Redis
- Геттеры и сеттеры
- Инкремент и декремент
- Работа с списками
- Работа с хэш-таблицами
- Работа с множествами
- Работа с упорядоченными множествами
- 5 последних уроков рубрики «PHP»
- Фильтрация данных с помощью zend-filter
- Контекстное экранирование с помощью zend-escaper
- Подключение Zend модулей к Expressive
- Совет: отправка информации в Google Analytics через API
- Подборка PHP песочниц
- Шпаргалка по Redis
- Ключи
- Типы данных Redis
- Базовые операции
- Строки/числа
- Списки
- Множества, упорядоченные множества
- Хеш-таблицы
- Pub/Sub, сообщения в Redis
Знакомимся с Redis
Узнаём, для чего эта СУБД нужна и как ею пользоваться.
Redis ( REmote DIctionary Server, «удалённый серверный словарь») — это нереляционная резидентная СУБД, хранящая данные в виде пар «ключ-значение».
От реляционных баз Redis отличается:
Разрабатывает приложения на Java, воспитывает двух котов: Котлин и Монго.
Для чего используют Redis
Redis обычно применяют:
Как начать работать с Redis
Самый лёгкий способ — запустить Redis в docker-контейнере (если не знаете, что это, — добро пожаловать сюда).
Запускаем контейнер командой:
Убедимся, что контейнер запущен:
Затем открываем новую сессию и интерфейс командной строки ( CLI ):
Можно и сразу перейти в консоль Redis:
Вот мы и готовы работать с Redis.
Основные команды
Рассмотрим основные операции на примере хеш-таблиц.
HSET — сохраняет значение по ключу:
В примере выше мы создали объект person1 с двумя полями ( name и age) и соответствующими значениями.
HGET — получение значения по ключу (для определённого поля):
Выше мы получили значение поля name у ключа person1.
HGETALL — получение всех пар «ключ-значение»:
Получили значения всех полей по ключу person1.
HKEYS и HVALS — получение всех ключей и соответствующих им значений:
Как работать с оставшимися структурами данных — смотрите в официальном руководстве.
Транзакции
Важно понимать, что транзакции в Redis не сохраняют целостность данных (сбой одной операции при выполнении блока транзакции не мешает исполнить другие).
После запуска команды multi интерфейс redis-cli ответил на каждую последующую состоянием QUEUED («в очереди»). Когда мы запустили команду exec, то получили выходные данные каждой команды из очереди.
Отменить транзакцию можно командой discard. Она предотвратит запуск всех команд, ранее поставленных в очередь, — и Redis снова будет выполнять команды в обычном режиме. Чтобы сообщить серверу, что вы открываете новую транзакцию, нужно снова запустить multi.
Важно понимать, что когда команда уже встала в очередь (то есть синтаксически верна), то, даже если она и вызовет ошибку при выполнении, остальные команды выполнятся всё равно. А вот если не встала (невалидна, вызвала ошибку при постановке в очередь), то Redis блок транзакции отклонит, даже не дождавшись exec. И если вы попытаетесь после этого выполнить exec, вам скажут, что транзакция была отклонена из-за предыдущих ошибок.
Как Redis обрабатывает ошибки внутри транзакций, читайте тут.
Механизм подписок
Он позволяет одному клиенту создать канал событий и публиковать туда сообщения, а другому — подписываться и читать эти сообщения (так можно создать простой чат).
Механизм подписок не гарантирует, что сообщение будет доставлено. Мы отправляем сообщение в канал, а кто его примет (и примет ли) — обещать не можем, стоит помнить об этом и не использовать подписки там, где важно обратное.
Итак, клиент подписывается на канал командой:
Redis — высокопроизводительное хранилище данных
Бодрый день, хаброчеловеки!
Что такое Redis?
Redis — это высокопроизводительное нереляционное распределённое хранилище данных. В отличие от Memcached, который может в любой момент удалить ваши данные, вытесняя старые записи новыми, Redis хранит информацию постоянно, таким образом он похож на MemcacheDB.
Чем Redis отличается от существующих решений?
API для работы с Memcached (MemcacheDB) позволяет хранить массивы, но эти массивы будут сериализованы и сохранены как строки, таким образом атомарные операции над такими массивами не возможны.
Redis позволяет хранить как строки, так и массивы, к которым можно применять атомарные операции pop / push, делать выборки из таких массивов, выполнять сортировку элементов, получать объединения и пересечения массивов.
Производительность
110000 запросов SET в секунду, 81000 запросов GET в секунду на Linux-сервере начального уровня (тесты).
Высокая скорость работы Redis обеспечивается тем, что данные хранятся в оперативной памяти и сохраняются на диск либо через равные промежутки времени, либо при превышении определённого количества не сохранённых запросов. Из этого вытекает, что используя Redis, вы можете потерять результаты нескольких последних запросов, что вполне приемлимо для большинства веб-приложений, учитывая, что обращение к Redis по скорости сравнимо с обращением к оперативной памяти. Тем не менее, потерь можно избежать через избыточность — Redis поддерживает неблокирующую master-slave репликацию.
Sharding
Redis, как и Memcached, может работать как распределённое хранилище на многих физических серверах. Такой функционал реализуется в клиентских библиотеках, и к сожалению, «из коробки» этот функционал реализован пока только в Ruby API, однако это не мешает вам хешировать ключ самостоятельно и получать ID сервера, к которому с этим ключом обращаться.
API для PHP доступно как в виде модуля, написанного на C, так и в виде PHP5 класса, который общается с Redis-сервером через сокеты, таким образом не требуется устанавливать модуль.
Кроме того существует PHP5 класс от отечественного разрабочика (с именем, заслуживающим доверия. Я серьёзно.) — IMemcacheClient. (Спасибо DYPA за на водку)
Перспективы развития
Разработка ведётся очень активно, комиты происходят почти каждый день, сейчас доступна версия Redis 0.900 (1.0 release candidate 1), которая очень скоро станет версией 1.0
В ближайшем будущем авторы обещают внедрить разные интересные фичи, в том числе и сжатие данных.
Лицензия и поддерживаемые платформы
Redis — написан на ANSI C и работает на большинстве POSIX-систем (Linux, MacOS X). Это бесплатное открытое ПО под BSD лицензией =)
Redis — главное хранилище? Что за хрень?!
Redis это размещаемое в памяти хранилище ключ-значение, обычно используемое для кэшей и подобных механизмов ускорения сетевых приложений. Мы, тем не менее, храним все наши данные в Redis — в нашей главной базе данных.
Сеть полна предупреждений и предостерегающих повествований об использовании подобного подхода. Есть ужасающие истории о потере данных, исчерпании памяти или людях неспособных эффективно управлять данными в Redis, вы, возможно, интересуетесь «О чём вы вообще думаете?». Так вот, наш рассказ, почему мы всё же решили использовать Redis и как мы преодолели все эти проблемы.
Прежде всего, я хотел бы подчеркнуть что большинство приложений вовсе не должны обращать внимания на костыли использованные, что бы пойти таким путём. Это было важно для нашего сценария использования, но мы можем быть граничным случаем.
Redis как хранилище данных
Redis быстр. Когда я говорю быстр, я имею в виду Быстр с заглавной буквы Б. Это по существу memcached с более продуманными типами данных, нежели просто строковые значения. Даже некоторые продвинутые операции такие, как пересечение множеств, выборка диапазонов zset, ослепительно быстры. Есть все поводы использовать Redis для быстроменяющихся активно запрашиваемых данных. Он довольно часто используется в качестве кэша, который может быть перестроен по данным из резервной базы данных. Это мощная замена memcached предоставляющая более продвинутое кэширование для различных видов хранимых вами данных.
Как и в memcached, всё находится в памяти. Redis сохраняется на диск, но он не сохраняет данные синхронно с тем как вы записываете их. Есть две причины из-за которых Redis в качестве главного хранилища — отстой:
— Вы вынуждены умещать все свои данные в памяти, и…
— Если сервер откажет между двумя синхронизациями с диском — вы потеряете всё что сидело в памяти.
Из-за этих двух проблем Redis обосновался в компактной нише в качестве временного кэша для данных которыми вы можете пожертвовать, но не главного хранилища данных. Предоставляя быстрый доступ к часто необходимым данным с возможностью перестроения при необходимости.
Недостаток использования более традиционных хранилищ за Redis заключается в затыке с производительностью этих хранилищ. Вам приходится жертвовать производительностью чтобы убедиться, что данные сохранены на диск. Совершенно нормальная сделка для почти каждого приложения. Вы можете получить великолепную производительность по чтению и «хорошую» производительность по записи. Я должен пояснить, что «хорошая» для меня вполне вероятно может быть безумно быстрая для большинства людей. Достаточно сказать, что «хорошая» производительность по записи должна удволетворить большинство, кроме самых высоко нагруженных приложений.
Я полагаю, что вы можете выполнить запрос на запись в Redis а потом сохраниться при помощи реляционного хранилища, но тогда остаются те же риски падения Redis и потери данных очереди записи.
Что нам нужно?
Moot предлагается как полностью бесплатный продукт. Нам, таким образом, необходимо иметь возможность обрабатывать крупные нагрузки на очень небольшом количестве железа. Если нам нужна куча больших баз данных для форума обслуживающего несколько миллионов пользователей в месяц, то нет никаких способов остаться бесплатным сервисом. Поскольку мы хотим, что бы Moot был и бесплатным и неограниченным, мы вынуждены были оптимизировать до предела.
Мы могли бы просто избежать этого установив какие-нибудь ограничения на бесплатные сервисы и брать деньги за просмотр страниц или постов. Не знаю как вы, но я, в общем, не люблю продукты, которые бесплатны «пока вы не раскрутитесь». Скажем, вы настроили форум, а потом что-то на вашем сайте станет вирусным. Внезапно, вас ошарашат счётом за превышение бесплатного уровня. И вот то, что начиналось как развлечение, из-за внезапной популярности вашего блога о теории заговоров, превращается в ужас грядущего счёта. Вас наказывают за ваш успех. Это то, чего мы хотели бы избежать.
Мы так же могли бы решить монетизироваться размещая рекламу, и позволив себе более высокие эксплуатационные расходы. Это, тем не менее, полностью расходится с нашим базовыми ценностями как бизнеса. По нашему мнению, если кто-то собирается размещать рекламу на вашем сайте, это должны быть вы а не мы. Moot должен предлагаться без условий, ограничений и приписок.
Принимая во внимание всё вышесказанное, необходимо достичь непревзойдённой производительности для постинга и чтения не взирая на инженерные сложности. Это базис для нашей возможности работать. У нас была изначальная цель, чтобы все вызовы API обрабатывались менее чем за 10мс даже под высокой нагрузкой, и даже тогда, когда обрабатываются большие сложные списки или поиски. Redis, очевидно, может обеспечить нам такую производительность, но две большие проблемы никуда не делись: Как, блин, мы сможем использовать Redis, если у нас могут быть сотни гигабайт данных, и что делать с падением сервера?
Что же теперь делать?
Так началось наше исследование способов проектирования с учётом этих ограничений. У нас с самого начала было точное понимание какими будут задачи у Moot, и наших ценностей как компании, поэтому нам повезло иметь возможность обдумать эти особенности до написания первых строчек кода. Я полагаю что эти проблемы были бы чрезмерно сложны, если бы мы решили пойти этим путём, имея множество готового кода.
Все данные в памяти. Блин.
Это самая сложна из двух проблем. Количество памяти, которое может быть на одном компьютере, конечно. Наибольшее количество на EC2 это 244-гигабайтный сервер. Хотя это по прежнему конечный объём, это довольно хороший лимит для начала. К сожалению, при этом ваш 16-ядерный сервер будет использовать только одно ядро для Redis. Что ж, как на счёт добавления по подчинённому процессу Redis на каждое ядро? Тогда у вас осталось по 15 ГБ памяти на каждый экземпляр. Опять фигня! Это плохое ограничение, если вы хотите иметь возможность выжать из сервера мощность. Это не достаточно данных для сервиса хостинга.
Мы решили спроектировать наше Redis-хранилище с самого начала разделённым среди множества Redis кластеров. Мы хэшируем и разделяем данные в блоки содержащие все структуры, относящиеся к данному сегменту данных. Данные сильно разделены с самого начала и мы можем по необходимости создавать новые блоки быстро и просто.
Для разбивки данных мы храним таблици хэшей и адресов примерно так:
Когда поступают данные, мы вычисляем хэш на основе наших требований к связности данных, потом мы проверяем в shards.map был ли он назначен какому-нибудь блоку, и если да — мы можем направить вызовы на тот блок.
Если хэш ещё не приписан к какому либо блоку, мы создаём список доступных блоков множа их в соответствии с весом. Если например выполнить:
Список будет выглядеть как-то так:
После этого мы назначаем случайный блок из списка, сохраняем в карту распределения и идём далее.
Применяя такую схему мы можем легко контролировать сколько данных поступает в блоки, добавлять новые блоки или даже исключать блоки из рассмотрения, если видим, что они заполнены.
Реально мы начали с сотен блоков так что нечего беспокоиться о нагрузке на сервера и ограничениях памяти.
Отдельные блоки остаются очень малыми. Один сервер содержит много блоков в базах данных Redis и, если эти блоки увеличиваются в размерах, мы легко можем разделить базы Redis на независимые экземпляры. Скажем у нас экземпляр Redis с 100 блоками, мы видим, что некоторые блоки увеличиваются в размере и мы разделяем Redis на два экземпляра по 50 блоков каждый. Мы можем точно настроить веса чтобы поддерживать распределение между блоками в реальном времени.
Самая сложная часть, это точно определить то, как вы сегментируете ваши данные. Это очень специфично и наш вариант сегментации, возможно, тема для отдельного поста.
Такая стратегия хранения должна разрабатываться в приложении с самого начала. Часто люди пытаются разделять данные, которые так не спроектированы, в этом то и загвоздка для их использования Redis. Поскольку мы чётко знали, что ограничение памяти будет проблемой, мы смогли спроектировать решение в самом ядре нашей системы управления данными, ещё до того как мы написали хоть одну строчку кода.
Падения сервера
Разобраться с отказами оказалось, смешно сказать, легче. У нас для кластера Redis было 3 разные роли:
— Мастер, где происходили почти все операции на запись,
— Подчинённый, гда происходили почти все чтения,
— Хранитель, выделенный для сохранения данных.
Мастер и подчинённый работают в общем как и любые другие в кластере Redis. В этом нет ничего интересного. Что мы сделали нового, это то что в каждом кластере есть по 2 сервера, используемых в качестве хранителей. Эти сервера:
— Не принимают никаких входящих соединений и не несут никакой нагрузки Redis запросов, кроме простой репликации
— Хранение AOF в ежесекундном режиме
— Ежечасный снимок RDB
— Синхронизируют AOF и RDB в S3
В виду того, что параметры производительности для хранения могут несколько различаться, один сервер хранитель может обработать различное количество блоков. Мы просто запускаем по одному экземпляру на каждый блок, который должен храниться. Другими словами, нет необходимости в отношении 1 к 1 между блоками и серверами с ролью хранителя.
У нас два этих сервера расположены в различных зонах доступности, так что даже если одна из зон выходит из строя, у нас есть работающий актуальный сервер-хранитель.
Таким образом, чтобы нам потерять данные необходим довольно большой отказ в EC2 и даже тогда, мы потеряем только около секунды данных.
Если вы рассматриваете сценарий нарушения связности сети, когда мастер может быть изолирован от подчинённых, его можно нивелировать проверкой репликации подчинённых(установить произвольный ключ в произвольное значение и проверить, обновились ли данные у подчинённого) Если мастер изолирован, мы останавливаем запись: Согласованность и Устойчивость к потере связности за счёт Доступности. Redis Sentinel тоже мог бы помочь нам с этим, но Sentinel был выпущен позже того, как мы реализовали большую часть системы. Мы не исследовали, как Sentinel мог бы вписаться бы в наше уравнение.
Конечный результат
В конце концов, мы смогли построить систему, которая под нагрузкой выполняет вызовы API за приблизительно 2 мс.
Значение 2 мс — при обслуживании нашего самого тяжёлого API-вызова, инициализационного API-вызова.
Многие наши запросы обслуживаются гораздо быстрее ( лайки например часто за 0.6-0.7 мс). Мы можем исполнять 1000 API запросов в секунду на одном API сервере. И для построения страницы требуется один API вызов. В замер включены все наши проверки данных, управление блоками, аутентификация, управление сессиями, соединениями, сериализация JSON и так далее.
Многое из этого заслуга не только ЭТИХ решений для Redis. Есть ещё несколько трюков для того, чтобы система производительно работала под высокой параллельной нагрузкой. Один из этик трюков в том, что почти половина нашего кода написана на Lua и работает прямо в Redis. Это другая вещь, которую в общем говорят не делать. Что касается того, как и почему у нас тысячи строк кода на Lua — подождите следующего поста о нашем применении Redis.
Взгляните на нашу реальную производительность, мы запустились пару дней назад, и получили неплохой начальный всплеск. Мы обслуживали 50 API вызовов в секунду и процессор нашего главного API сервера (мы до сих пор посылаем весь трафик на один) был полностью в простое. Вот графики, начиная с нашего запуска до момента написания поста.
Во время наших пиковых нагрузок всё тихо. Вы можете заметить пару всплесков, когда мы накатывали хотфиксы, но в остальном ни шороха. Более поздние всплески соответствуют обновлениям системы, исправлениям и другим проводимым системным работам. Общая нагрузка так же включает увеличенные накладные расходы на логгирование которое мы вели в период начального бета теста.
Пояснение: я ссылаюсь на API сервер как на замеряемый, так как наш сервер приложений и Redis сервер это одно и тоже. API сервер несёт на себе как несколько блоков, так и приложение. Идея была в том, чтобы маршрутизировать трафик на сервер где в основном расположен этот блок, чтобы воспользоваться unix-сокетами для подключения к Redis. Это позволят избегать излишнего сетевого трафика поэтому нет особого различия между Сервером приложений, Redis мастером и Redis подчинённым. Любой API сервер может обработать любой запрос, просто мы даём гораздо больший приоритет мастер серверу задействованного сегмента данных. Все серверы — серверы приложений, и все серверы — мастера для каких-то блоков и подчинённые для других.
tl;dr
Есть множество причин не использовать Redis как главное хранилище на жёстком диске, но если, по каким-то причинам, ваш вариант использования требует этого, вам необходимо начинать с самого начала. Вам стоит проектировать ваши данные разделёнными и помнить о дополнительной стоимости выделенных серверов хранения.
Стартуем работу с Redis и PHP
Об этой статье
Данная статья не является руководством по работе с Redis (для этого можете посетить официальный сайт). В данной статье мы рассмотрим как связать Redis и PHP.
Установка Redis
Процесс установки абсолютно не вызывает трудностей. Просто следуйте инструкциям, изложенным на официальном сайте.
Установка Redis на Linux
Для установке Redis на Linux вам потребуется TCL. Запустите команду:
$ sudo apt-get install tcl
Для установки Redis:
$ wget http://download.redis.io/releases/redis-2.8.19.tar.gz
$ tar xzf redis-2.8.19.tar.gz
$ cd redis-2.8.19
$ make
Заметка: значение 2.8.19 замените на номер текущей стабильной версии.
Все бинарные файлы будут сохранены в каталоге SRC. Для запуска сервера:
Установка Redis на Windows
Для установки Redis на Windows просто скачайте последний пакет и следуйте инструкциям.
$ git clone git://github.com/nrk/predis.git
Подключение к Redis
Для начала подключаем автозагрузчик Redis. Затем помещаем код в блок try/catch. Подключение к локальному Redis выглядит несколько иначе, чем к удалённому.
Теперь, когда подключение произошло, можем приступать к работе с Redis.
Типы данных в Redis
Redis поддерживает целый ряд типов данных. Вы можете спросить какое это имеет значение для NOSQL базы данных? Это позволяет хранить данные в том виде, в котором это целесообразней и в некоторых случаях влияет на скорость доступа к данным.
Есть ещё и другие типы данных, такие как битмапы и иероглифы, но их мы рассматривать не будем.
Геттеры и сеттеры
Инкремент и декремент
Работа с списками
Для работы со списками вам понадобятся команды:
Просто использование списков:
Работа с хэш-таблицами
Как уже упоминалось, данный тип можно сопоставить с ассоциативными таблицами. Команды:
Работа с множествами
Список команд: – SADD : добавление числа N ключу – SREM : удаление числа N ключу – SISMEMBER : проверка существование значения – SMEMBERS : набор всех значений.
Работа с упорядоченными множествами
Мы рассмотрели лишь самые необходимые команды. Все остальные можно найти на сайте Redis.
Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: https://scotch.io/tutorials/getting-started-with-redis-in-php
Перевел: Станислав Протасевич
Урок создан: 24 Апреля 2015
Просмотров: 71280
Правила перепечатки
5 последних уроков рубрики «PHP»
Фильтрация данных с помощью zend-filter
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Контекстное экранирование с помощью zend-escaper
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Подключение Zend модулей к Expressive
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Совет: отправка информации в Google Analytics через API
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.
Шпаргалка по Redis
Про Redis (официальный сайт, материалы на Хабре) написано много, но мне до сего дня не хватало материала, который послужил бы шпаргалкой по его практическому использованию, а так же справочником по базовым теоретическим моментам. Постараюсь заполнить этот пробел в богатой базе знаний Хабра.
Я поставил перед собой цель показать возможности Redis с помощью примеров кода. После публикации приму любые предложения по улучшению материала.
Здесь используется общение с сервером через консольный клиент, но, основываясь на приведенных примерах, можно легко найти реализацию этих примеров в клиентских библиотеках на вашем любимом языке.
Ключи
Типы данных Redis
Базовые операции
Подробности о командах, связанных с этой задачей можно найти в документации в разделах Keys и Strings.
Задача 2, время жизни объекта.
Подробности о командах, связанных с этой задачей можно найти в документации в разделах Keys и Strings.
Задача 3, pipelining, выполнение нескольких команд одним запросом.
Pipelining удобно использовать для оптимизации массовых вставок.
Подробности о командах, связанных с этой задачей можно найти в документации в разделе Transactions.
Строки/числа
Задача 5, продемонстрировать основные строковые операции.
Задача 6, продемонстрировать операции над числами.
Подробности о командах, связанных с этими задачами можно найти в документации в разделе Strings.
Списки
Задача 7, создать список, продемонстрировать основные операции над списками.
Подробности о командах, связанных с этой задачей можно найти в документации в разделе Lists.
Множества, упорядоченные множества
Задача 8, создать множество, продемонстрировать основные операции над множествами.
Подробности о командах, связанных с этой задачей можно найти в документации в разделе Sets.
Задача 9, создать упорядоченное множество и продемонстрировано основные операции над ним.
В упорядоченном множестве элементы сравниваются по дополнительному параметру «score».
Подробности о командах, связанных с этой задачей можно найти в документации в разделе Sorted sets.
Хеш-таблицы
Задача 10, Создать хеш-таблицу и продемонстрировать основные операции над хешами.
Подробности о командах, связанных с этой задачей можно найти в документации в разделе Hashes.
Pub/Sub, сообщения в Redis
Задача 11, подписаться на сообщения на одном клиенте и отправить сообщение из другого.
Приведем окна двух клиентов, в первом окне совершается подписка на сообщения и видно отправленное из второго окна сообщение.
Задача 12, подписаться на сообщения на одном клиенте и отправить сообщение из другого. Подписку осуществить с помощью шаблонов.
Приведем окна двух клиентов, в первом окне совершается подписка на сообщения и видно отправленное из второго окна сообщение.
Подробности о командах, связанных с этими задачами можно найти в документации в разделе Pub/Sub.