KV хранилище
При работе над бэкэндом сколько-нибудь крупного проекта перед разработчиком рано или поздно встает вопрос выбора хранилища. На определенном этапе РСУБД перестает удовлетворять потребности проекта:
Требование на быструю запись/чтение. При высоких нагрузках скорость ответа от базы растет. РСУБД можно ускорять разными путями: оптимизировать настройки, профилировать и улучшать запросы, шардировать и реплицировать. Однако эти оптимизации все равно не позволят стабильно отвечать на запросы за несколько мс.
Строгая структура таблиц. Сегодня в любом бизнесе важна скорость доставки ценности до конечного пользователя. Вследствие этого на проектах происходят частые изменения, которые затрагивают схемы таблиц. Сперва может показаться, что это не проблема, но, во-первых, составление миграций занимает время, во-вторых, в таблице может храниться слишком много записей для изменений "в бою".
В вышеперечисленных случаях можно использовать key-value (далее "KV") хранилища.
Redis как key-value хранилище
Рассмотрим стандартный пример использования Redis как KV: хранение информации о сессиях пользователей. Когда пользователь авторизуется на сайте, генерируется идентификатор сессии и используется как ключ. В значении сохранятся идентификатор пользователя (user_id) и любая нужная персональная информация. Обычно сессия записывается в cookie браузера. После этого backend моментально определяет, от какого пользователя пришел запрос.
Запись новой сессии

Попробуем реализовать пример на практике. Представим, что пользователь с идентификатором 120 авторизовался, и серверу нужно создать для него сессию. Обычно идентификатор сессии состоит из большой рандомизированной строки. В данном уроке для простоты будет использоваться числовое представление.
Подключаемся к Redis серверу с помощью redis-cli и записываем значение user_id по ключу сессии:
Команда записи в Redis имеет простую конструкцию:
Сразу стоит обратить внимание на пару важных моментов:
в ключах рекомендуется использовать двоеточие как разделитель слов (хотя и встречаются другие подходы к наименованию). В примере с сессией ключ имеет вид
session:{session_id}.команда
setзаписывает значение как строку. Одиночное слово пишется без кавычек, но предложение придется писать в одинарных или двойных кавычкахset key1 'hello world'.
Получение существующей сессии

Сессия сформирована и записана в Redis и cookie. Теперь при следующем запросе от клиента сервер увидит сессию и пойдет в Redis, чтобы определить пользователя:
Redis вернул строку, так как сессия существовала. Но что будет, если клиент пришлет несуществующую сессию?
Вернется значение (nil), означающее отсутствие ключа.
Если необходимо проверить сессию на существование без получения идентификатора пользователя, то используется соответствующая команда:
Если ключ существует, Redis возвращает целое число 1. В противном случае вернется 0.
Удаление сессии

При выходе из аккаунта сессия пользователя должна удаляться:
Ответ Redis идентичен команде exists:
1, если ключ существовал, и он был успешно удален0, если ключа не было, поэтому ничего не было удалено
Хранение дополнительной информации
Допустим, в сессии нужно хранить не только идентификатор (user_id), но и электронную почту пользователя (email). Для этого достаточно в значение положить JSON-объект, содержащий всю необходимую информацию:
Этот метод имеет некоторые недостатки:
логика по конвертированию в JSON выносится на уровень приложения. В следующих уроках мы рассмотрим стандартный тип данных в Redis, который позволяет хранить несколько значений по одному ключу
для получения одного поля
user_idнужно достать весь JSON и декодировать его. В Redis существует модуль RedisJSON для решения этой проблемы. Например, получение поля реализуется одной командой:
Резюме
БД в проекте выбираются под конкретные задачи.
в Redis все значения хранятся по ключам. Абстрактно можно представить в виде хэш-таблицы или словаря. Из-за этого любое чтение/запись имеет очень высокую производительность. Например, Redis без труда выполняет запрос за 3мс при нагрузке в 5000+ RPS (запросов в секунду).
в Redis хранятся неструктурированные значения. Если необходимо добавить новое поле в существующую структуру, то изменения вносятся только на уровне кода.
основные команды для работы со значениями:
set,get,del,exists.
Дополнительные материалы
Вопросы для самопроверки
Представим, что в проекте необходимо хранить данные авиарейсов, пассажиров и линий выдачи багажа для прибывающих пассажиров. Ресурс не нагруженный, и нет ограничений по скорости ответа. Какой тип хранилища лучше использовать?
key-value хранилище, потому что данные можно получить быстро
key-value хранилище, потому что всех пассажиров рейса удобнее хранить в одном ключе
РСУБД, потому что между данными существуют отношения
Допишите команду получения данных ключа user:1 из Redis
___ user:1
Допишите команду записи электронной почты test@test.com пользователя по ключу user:1 в Redis
___ user:1 ___
Какие преимущества key-value хранилища перед РСУБД? (нужно выбрать все корректные ответы)
динамическая структура хранимых данных
удобное получение агрегированных данных с помощью специального языка запросов
скорость чтения/записи атомарных значений
строгая типизация данных по ключам
Допишите команду удаления данных по ключу user:10 в Redis.
___ user:10