Redis: основные типы данных и операции

Redis — это популярная нереляционная база данных, реализующая хранилище типа «Ключ — Значение». Данная статья посвящена основным типам данных и операциям и является вступительной к серии статей о Redis, в рамках которой будет рассматриваться и работа с Redis при помощи Spring Data.

Что такое Redis

Redis — это хранилище данных типа «Ключ — Значение» (аналог Map в Java, Kotlin и других языках программирования). В отличие от более традиционных реляционных баз данных вроде MySQL и PostgreSQL или нереляционных вроде MongoDB и Cassandra, в Redis отсутствуют таблицы и коллекции, а вся база данных представляет собой справочник, состоящий из ключей и значений. По умолчанию Redis может хранить до 4 294 967 295 (2^32-1) пар «ключ — значение».

При этом Redis является высокопроизводительной базой данных: заявляется о производительности в 100 000 GET/SET-команд в секунду на сервере начального уровня под управлением GNU/Linux, что делает Redis весьма мощным инструментом для ряда задач, вроде кеширования, индексации, организации поиска и аналитики. Обеспечивается такая производительность, в том числе, за счёт хранения данных в оперативной памяти.

Основные типы данных

Redis OSS поддерживает следующие типы данных для значений: строки, хеш-таблицы, списки, множества, потоки, битовые карты и поля, а так же геопространственные структуры. Кроме этого Redis Stack и Redis Enterprise поддерживают JSON, вероятностные структуры данных и временные ряды. Предлагаю вкратце разобраться с основными типами данных.

Строки (String)

Строки являются основным типом данных в Redis для значений, а для ключей — и вовсе единственным. С точки зрения разработчиков программного обеспечения на языках программирования вроде Java, Kotin и других, Redis в целом можно представить себе как Map<String, String>.

По умолчанию максимальный размер строкового значения составляет 512Мб.

Основные операции

  • set <key> <value> — устанавливает значение для указанного ключа
  • get <key> — возвращает текущее значение или nil
  • del <key> — удаляет значение, применима ко всем ключам, вне зависимости от типа значения

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

Хеш-таблицы (Hash table)

Хеш-таблицы представляют собой структуру типа «ключ — значение». Redis позволяет хранить до 4 294 967 295 (2^32-1) пар «ключ — значение» в хеш-таблице.

Аналог хеш-таблиц в Java — HashMap.

Основные операции

  • hset <key> <hashkey> <hashvalue> — установка значения в хеш-таблице, при этом пары hashkey-hashvalue могут повторяться. Если значение присваивается существующей хеш-таблице, то существующие значения будут заменены новыми.
  • hget <key> <hashkey> — получение значения из хеш-таблицы
  • hmget <key> <hashkey1> <hashkey2> — получение значений для одного и более ключей из хеш-таблицы
  • hgetall <key> — получение всех ключей и значений указанной хеш-таблицы
  • hdel <key> <hashkey1> <hashkey2> — удаление указанных ключей из хеш-таблицы

Списки (List)

Списки представляют собой упорядоченные последовательности элементов и во многих языках программирования реализованы с использованием массивов (например, ArrayList в Java), но в Redis списки являются именно связанными списками, благодаря чему при помощи их можно реализовывать, например, логику очередей. Списки в Redis могут содержать дублирующиеся элементы.

Аналог списков Redis в Java — LinkedList.

Основные операции

  • lpush <key> <element1> <element2> <elementn> (left push) — добавление элементов в начало (левый край) списка
  • rpush <key> <element1> <element2> <elementn> (right push) — добавление элементов в конец (правый край) списка

При вставке нескольких элементов в начало списка стоит помнить, что элементы вставляются в список поочерёдно, а не вместе. Если вызвать операцию lpush list element1 element2, то фактический порядок элементов в списке будет element2 element1, так как сначала в начало списка будет добавлен element1, а затем в начало же списка будет добавлен element2. При вызове операции rpush порядок вставляемых элементов не изменяется.

  • llen <key> (list length) — получение количества элементов списка
  • lrange <key> <start> <stop> (list range) — получение элементов списка без их удаления. При помощи start и stop можно выбирать диапазон получаемых значений, первый элемент имеет позицию 0, диапазон указывается включительно. В качестве верхней границы можно указывать число, превышающее реальное количество элементов в списке или -1, в этом случае будут возвращены все элементы списка.
  • lpop <key> <count> (left pop) — извлечение элементов из начала списка. Возвращает и удаляет указанное количество элемент из начала списка (по умолчанию 1).
  • rpop (right pop) — извлечение элемента из конца списка. Возвращает и удаляет указанное количество элемент из начала списка (по умолчанию 1). При извлечении двух и более элементов из конца списка элементы будут возвращены в обратном порядке, так как извлекаться будут по очереди из конца списка.
  • blpop <key> <timeout> (blocking left pop) — блокирующее извлечение элемента из начала списка. Возвращает и удаляет элемент из начала списка. Если список пуст, то дожидается появления первого элемента указанное количество секунд.
  • ltrim <key> <start> <stop> (list trim) — усечение списка до указанного диапазона, диапазон задаётся от 0, границы указываются включительно
  • lmove <source> <destination> <left|right> <left|right> (list move) — атомарное перемещение элемента из одного списка в другой.
  • blmove <source> <destination> <left|right> <left|right> <timeout> (blocking list_move) — атомарное блокирующее перемещение элемента из одного списка в другой. Поведение аналогично lmove, но появляется таймаут ожидания, если исходный список пустой.

Множества (Set)

Множество (set) представляют собой неупорядоченный набор уникальных элементов.

Аналог множества Redis в Java — HashSet.

Основные операции

  • sadd <key> <element1> <element2> <elementN> (set add) — добавление элементов в множество
  • scard <key> (set cardinality) — получение количества элементов множества
  • smembers <key> (set members) — вывод элементов множества
  • srem <key> <element1> <element2> <elementN> (set remove) — удаление элементов из множества
  • sismember <key> <value> (set is member) — проверка, является ли значение элементом указанного множества
  • sinter <key1> <key2> <keyN> (set intersection) — получение элементов, которые встречаются во всех указанных множествах

Сортированные множества (Sorted Set)

Сортированные множества представляют собой наборы уникальных элементов, отсортированных по весу (score). Если несколько элементов имеют одинаковый вес, то они сортируются по алфавиту.

В некоторой мере аналогом сортированных множеств в Java является SortedSet и его реализации.

Основные операции

  • zadd <key> <nx|xx> <gt|lt> <ch> <incr> <score> <member> — добавление элемента в сортированное множество. Аргументы операции:
    • nx — только добавлять новые элементы, не изменяя существующие
    • xx — только изменять существующие элементы, не добавляя новые
    • gt — обновлять элементы только, если новый вес больше существующего
    • lt — обновлять элементы только, если новый вес меньше существующего
    • ch — показывать количество изменённых элементов, а не добавленных
    • incr — увеличивать существующий вес на указанный (может быть использован только с одной парой вес-элемент)
    • score — вес элемента
    • member — элемент

Команда zadd может принимать несколько пар вес-элемент (score member), если не используется аргумент incr. Аргументы nxgt и lt являются взаимоисключающими.

  • zcard <key> — получение количества элементов множества
  • zcount <key> <score-min> <score-max> — получение количества элементов множества в указанном диапазоне весов. Границы диапазона указываются включительно.
  • zrange <key> <start> <stop> <byscore | bylex> <rev> <limit offset count> <withscores> — получение элементов множества. Аргументы операции:
  • start и stop — диапазон элементов множества, числа если используется сортировка по весу, иначе элементы списка с ведущей [ или ( для указания включения или исключения элемента в диапазоне, либо - + — для использования всего диапазона.
  • byscore | bylex — сортировка по весу или алфавитному порядку
  • rev — получение элементов в обратном порядке
  • limit offset count — дополнительное ограничение получаемого подмножества
  • withscores — возврат элементов с весами (если не указан аргумент bylex)
  • zrank <key> <member> <withscore> — получение позиции элемента во множестве

Итого

В данной статье я вкратце рассказал о том, что такое Redis, описал наиболее используемые типы данных и основным операции с ними. В будущих статьях каждый тип данных будет рассмотрен более подробно, а так же будет описана работа с Redis в проектах на Java.