Знакомимся с Redis
Узнаём, для чего эта СУБД нужна и как ею пользоваться.


pierre borthiry / unsplash
Redis (REmote DIctionary Server, «удалённый серверный словарь») — это нереляционная резидентная СУБД, хранящая данные в виде пар «ключ-значение».
От реляционных баз Redis отличается:
- более высокой производительностью (благодаря хранению данных в оперативной памяти сервера, значительно увеличивается число выполняемых операций);
- отсутствием языка SQL (Lua-скрипты как альтернатива);
- гибкостью (данные находятся не в жёстких структурах (таблицах), а в более удобных (строки, списки, хеши, множества, сортированные множества), что облегчает работу программисту;
- лучшей масштабируемостью.
Однако Redis редко используется как основное хранилище в крупных системах, так как не удовлетворяет требованиям ACID, то есть не обеспечивает 100%-ной целостности данных.
Для чего используют Redis
Redis обычно применяют:
- для хранения пользовательских сессий (HTML-фрагменты веб-страниц или товары корзины интернет-магазина);
- для хранения промежуточных данных (поток сообщений на стене, голосовалки, таблицы результатов);
- как брокер сообщений (стратегия «издатель-подписчик» позволяет создавать новостные ленты, групповые чаты);
- как СУБД для небольших приложений, блогов;
- для кэширования данных из основного хранилища, что значительно снижает нагрузку на реляционную базу данных;
- для хранения «быстрых» данных — когда важны скорость и критичны задержки передачи (аналитика и анализ данных, финансовые и торговые сервисы).
Как начать работать с Redis
Самый лёгкий способ — запустить Redis в docker-контейнере (если не знаете, что это, — добро пожаловать сюда).
Запускаем контейнер командой:
docker run -d -p 6379:6379 --name my-redis redis
Убедимся, что контейнер запущен:
docker ps

Затем открываем новую сессию и интерфейс командной строки (CLI):
docker exec -it my-redis sh
redis-cli

Можно и сразу перейти в консоль Redis:
docker exec -it my-redis redis-cli

Вот мы и готовы работать с Redis.
Основные команды
Redis поддерживает операции со строками, списками, множествами, хеш-таблицами, упорядоченными множествами и так далее.
Рассмотрим основные операции на примере хеш-таблиц.
HSET — сохраняет значение по ключу:
127.0.0.1:6379> HSET person1 name "Aleksey"
(integer) 1
127.0.0.1:6379> HSET person1 age 25
(integer) 1
В примере выше мы создали объект person1 с двумя полями (name и age) и соответствующими значениями.
HGET — получение значения по ключу (для определённого поля):
127.0.0.1:6379> HGET person1 name
"Aleksey"
Выше мы получили значение поля name у ключа person1.
HGETALL — получение всех пар «ключ-значение»:
127.0.0.1:6379> HGETALL person1
1) "name"
2) "Aleksey"
3) "age"
4) "25"
Получили значения всех полей по ключу person1.
HKEYS и HVALS — получение всех ключей и соответствующих им значений:
127.0.0.1:6379> HKEYS person1
1) "name"
2) "age"
127.0.0.1:6379> HVALS person1
1) "Aleksey"
2) "25"
Как работать с оставшимися структурами данных — смотрите в официальном руководстве.
Транзакции
Важно понимать, что транзакции в Redis не сохраняют целостность данных (сбой одной операции при выполнении блока транзакции не мешает исполнить другие).
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCR counter1
QUEUED
127.0.0.1:6379> INCR counter1
QUEUED
127.0.0.1:6379> DECR counter2
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 2
3) (integer) -1
После запуска команды multi интерфейс redis-cli ответил на каждую последующую состоянием QUEUED («в очереди»). Когда мы запустили команду exec, то получили выходные данные каждой команды из очереди.
Отменить транзакцию можно командой discard. Она предотвратит запуск всех команд, ранее поставленных в очередь, — и Redis снова будет выполнять команды в обычном режиме. Чтобы сообщить серверу, что вы открываете новую транзакцию, нужно снова запустить multi.
Важно понимать, что когда команда уже встала в очередь (то есть синтаксически верна), то, даже если она и вызовет ошибку при выполнении, остальные команды выполнятся всё равно. А вот если не встала (невалидна, вызвала ошибку при постановке в очередь), то Redis блок транзакции отклонит, даже не дождавшись exec. И если вы попытаетесь после этого выполнить exec, вам скажут, что транзакция была отклонена из-за предыдущих ошибок.
Как Redis обрабатывает ошибки внутри транзакций, читайте тут.
Механизм подписок
Он позволяет одному клиенту создать канал событий и публиковать туда сообщения, а другому — подписываться и читать эти сообщения (так можно создать простой чат).
Механизм подписок не гарантирует, что сообщение будет доставлено. Мы отправляем сообщение в канал, а кто его примет (и примет ли) — обещать не можем, стоит помнить об этом и не использовать подписки там, где важно обратное.
Итак, клиент подписывается на канал командой:
127.0.0.1:6379> SUBSCRIBE channel1
Reading messages... (press Ctrl-C to quit)
Другой клиент публикует сообщения вот так:
127.0.0.1:6379> PUBLISH channel1 "Hello! My name is Maksim!"
(integer) 1
Целочисленное значение (в нашем случае 1), которое получено в результате публикации, это число подписчиков, получивших сообщение.
В результате в консоли первого клиента появится введённое сообщение:

