
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>— устанавливает значение для указанного ключа
|
1 2 3 |
# Присваивание значения bar ключу foo 127.0.0.1:6379> set foo bar OK |
get <key>— возвращает текущее значение или nil
|
1 2 3 4 5 6 7 |
# Получение несуществующего значения 127.0.0.1:6379> get baz (nil) # Получение существующего значения 127.0.0.1:6379> get foo "bar" |
del <key>— удаляет значение, применима ко всем ключам, вне зависимости от типа значения
|
1 2 3 |
# Удаление значения 127.0.0.1:6379> del foo (integer) 1 |
Строки в Redis могут себя вести как числа, битовые карты и поля, более подробно это и остальные операции будут рассмотрены в одной из следующих статей.
Хеш-таблицы (Hash table)
Хеш-таблицы представляют собой структуру типа «ключ — значение». Redis позволяет хранить до 4 294 967 295 (2^32-1) пар «ключ — значение» в хеш-таблице.
Аналог хеш-таблиц в Java — HashMap.
Основные операции
hset <key> <hashkey> <hashvalue>— установка значения в хеш-таблице, при этом пары hashkey-hashvalue могут повторяться. Если значение присваивается существующей хеш-таблице, то существующие значения будут заменены новыми.
|
1 2 3 4 5 6 7 8 9 10 11 |
# Пример установки ключа manufacturer в хеш-таблице car 127.0.0.1:6379> hset car manufacturer Chevrolet (integer) 1 # Пример установки новых значений для ключей model и year 127.0.0.1:6379> hset car manufacturer Chevrolet model Tahoe year 2024 (integer) 2 # Количество добавленных ключей (model и year) # Пример замены значений для ключей manufacturer и model 127.0.0.1:6379> hset car manufacturer Ford model Expedition year 2024 (integer) 0 |
hget <key> <hashkey>— получение значения из хеш-таблицы
|
1 2 |
127.0.0.1:6379> hget car manufacturer "Ford" |
hmget <key> <hashkey1> <hashkey2>— получение значений для одного и более ключей из хеш-таблицы
|
1 2 3 |
127.0.0.1:6379> hmget car manufacturer year "Ford" "2024" |
hgetall <key>— получение всех ключей и значений указанной хеш-таблицы
|
1 2 3 4 5 6 7 |
127.0.0.1:6379> hgetall car 1) "manufacturer" 2) "Ford" 3) "model" 4) "Expedition" 5) "year" 6) "2024" |
hdel <key> <hashkey1> <hashkey2>— удаление указанных ключей из хеш-таблицы
|
1 2 |
127.0.0.1:6379> hdel car year (integer) 1 |
Списки (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 порядок вставляемых элементов не изменяется.
|
1 2 3 4 5 |
127.0.0.1:6379> lpush manufacturers Ford Chevrolet # добавление двух элементов в начало списка (integer) 2 # количество элементов в списке 127.0.0.1:6379> rpush manufacturers GMC # добавление элемента в конец списка (integer) 3 # количество элементов в списке |
llen <key>(list length) — получение количества элементов списка
|
1 2 |
127.0.0.1:6379> llen manufacturers # получение количества элементов (integer) 3 # количество элементов в списке |
lrange <key> <start> <stop>(list range) — получение элементов списка без их удаления. При помощи start и stop можно выбирать диапазон получаемых значений, первый элемент имеет позицию 0, диапазон указывается включительно. В качестве верхней границы можно указывать число, превышающее реальное количество элементов в списке или -1, в этом случае будут возвращены все элементы списка.
|
1 2 3 4 5 6 7 8 9 10 11 |
127.0.0.1:6379> lrange manufacturers 0 -1 # получение всех элементов 1) "Chevrolet" 2) "Ford" 3) "GMC" 127.0.0.1:6379> lrange manufacturers 0 1 # получение элементов 0 и 1 1) "Chevrolet" 2) "Ford" 127.0.0.1:6379> lrange manufacturers 1 1 # получение элемента 1 1) "Ford" |
lpop <key> <count>(left pop) — извлечение элементов из начала списка. Возвращает и удаляет указанное количество элемент из начала списка (по умолчанию 1).rpop(right pop) — извлечение элемента из конца списка. Возвращает и удаляет указанное количество элемент из начала списка (по умолчанию 1). При извлечении двух и более элементов из конца списка элементы будут возвращены в обратном порядке, так как извлекаться будут по очереди из конца списка.
|
1 2 3 4 5 6 7 8 9 |
127.0.0.1:6379> lpop manufacturers # извлечение элемента из начала списка "Chevrolet" 127.0.0.1:6379> rpop manufacturers 2 # извлечение 2-х элементов из конца списка 1) "GMC" 2) "Ford" 127.0.0.1:6379> rpop manufacturers # извлечение элемента из конца пустого списка (nil) |
blpop <key> <timeout>(blocking left pop) — блокирующее извлечение элемента из начала списка. Возвращает и удаляет элемент из начала списка. Если список пуст, то дожидается появления первого элемента указанное количество секунд.
|
1 2 3 4 5 6 7 8 9 10 |
# блокирующее извлечение элемента из начала списка с таймаутом в 3 секунды 127.0.0.1:6379> blpop manufacturers 3 (nil) # элемент не появился (3.06s) # затраченное время # блокирующее извлечение элемента из начала списка с таймаутом в 5 секунд 127.0.0.1:6379> blpop manufacturers 5 1) "manufacturers" 2) "Chevrolet" # элемент появился (2.56s) # затраченное время |
ltrim <key> <start> <stop>(list trim) — усечение списка до указанного диапазона, диапазон задаётся от 0, границы указываются включительно
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Добавляем в список 5 элемента 127.0.0.1:6379> lpush manufacturers Ford Chevrolet GMC Jeep Dodge (integer) 5 # Список 127.0.0.1:6379> lrange manufacturers 0 -1 1) "Dodge" 2) "Jeep" 3) "GMC" 4) "Chevrolet" 5) "Ford" # Усекаем список до элементов 2-4 127.0.0.1:6379> ltrim manufacturers 2 4 OK # Полученный список 127.0.0.1:6379> lrange manufacturers 0 -1 1) "GMC" 2) "Chevrolet" 3) "Ford" |
lmove <source> <destination> <left|right> <left|right>(list move) — атомарное перемещение элемента из одного списка в другой.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# Добавляем в список 5 элемента 127.0.0.1:6379> lpush manufacturers Ford Chevrolet GMC Jeep Dodge (integer) 5 # Список 127.0.0.1:6379> lrange manufacturers 0 -1 1) "Dodge" 2) "Jeep" 3) "GMC" 4) "Chevrolet" 5) "Ford" # Переместим первый элемент manufacturers в конец списка usmanufacturers 127.0.0.1:6379> lmove manufacturers usmanufacturers left right "Dodge" # перемещённый элемент # Состояние списков 127.0.0.1:6379> lrange manufacturers 0 -1 1) "Jeep" 2) "GMC" 3) "Chevrolet" 4) "Ford" 127.0.0.1:6379> lrange usmanufacturers 0 -1 1) "Dodge" # Переместим последний элемент manufacturers в начало списка usmanufacturers 127.0.0.1:6379> lmove manufacturers usmanufacturers right left "Ford" # перемещённый элемент # Состояние списков 127.0.0.1:6379> lrange manufacturers 0 -1 1) "Jeep" 2) "GMC" 3) "Chevrolet" 127.0.0.1:6379> lrange usmanufacturers 0 -1 1) "Ford" 2) "Dodge" |
blmove <source> <destination> <left|right> <left|right> <timeout>(blocking list_move) — атомарное блокирующее перемещение элемента из одного списка в другой. Поведение аналогичноlmove, но появляется таймаут ожидания, если исходный список пустой.
|
1 2 3 4 5 6 7 8 |
# Переместим первый элемент manufacturers в конец списка usmanufacturers с таймаутом 5 секунд 127.0.0.1:6379> blmove manufacturers usmanufacturers left right 5 "Dodge" # перемещённый элемент # Попытаемся переместить элемент из пустого списка 127.0.0.1:6379> blmove manufacturers usmanufacturers right left 5 (nil) # перемещаемый элемент отсутствует (5.06s) # затраченное время |
Множества (Set)
Множество (set) представляют собой неупорядоченный набор уникальных элементов.
Аналог множества Redis в Java — HashSet.
Основные операции
sadd <key> <element1> <element2> <elementN>(set add) — добавление элементов в множество
|
1 2 3 |
# Добавление 5 элементов в множество manufacturers 127.0.0.1:6379> sadd manufacturers Ford Chevrolet Dodge Jeep GMC (integer) 5 # количество добавленных элементов |
scard <key>(set cardinality) — получение количества элементов множества
|
1 2 |
127.0.0.1:6379> scard manufacturers (integer) 6 |
smembers <key>(set members) — вывод элементов множества
|
1 2 3 4 5 6 |
127.0.0.1:6379> smembers manufacturers 1) "Ford" 2) "Chevrolet" 3) "Dodge" 4) "Jeep" 5) "GMC" |
srem <key> <element1> <element2> <elementN>(set remove) — удаление элементов из множества
|
1 2 3 4 5 6 7 8 9 |
# Удаление элементов Jeep и Ford из множества 127.0.0.1:6379> srem manufacturers Jeep Ford (integer) 2 # количество удалённых элементов # Итоговое множество 127.0.0.1:6379> smembers manufacturers 1) "Chevrolet" 2) "Dodge" 3) "GMC" |
sismember <key> <value>(set is member) — проверка, является ли значение элементом указанного множества
|
1 2 3 4 5 6 7 |
# Проверка, является ли Chevrolet элементом множества manufacturers 127.0.0.1:6379> sismember manufacturers Chevrolet (integer) 1 # да # Проверка, является ли Ford элементом множества manufacturers 127.0.0.1:6379> sismember manufacturers Ford (integer) 0 # нет |
sinter <key1> <key2> <keyN>(set intersection) — получение элементов, которые встречаются во всех указанных множествах
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Добавление 6 элементов в множество manufacturers 127.0.0.1:6379> sadd manufacturers Ford Chevrolet GMC BMW Toyota Audi (integer) 6 # Добавление 3 элементов в множество usmanufacturers 127.0.0.1:6379> sadd usmanufacturers Ford Chevrolet GMC (integer) 3 # Поиск общих элементов 127.0.0.1:6379> sinter manufacturers usmanufacturers 1) "Ford" 2) "Chevrolet" 3) "GMC" |
Сортированные множества (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. Аргументы nx, gt и lt являются взаимоисключающими.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# Добавление в множество трёх элементов 127.0.0.1:6379> zadd manufacturers 10 Chevrolet 20 GMC 30 Ford (integer) 3 # Содержимое множества 127.0.0.1:6379> zrange manufacturers 0 -1 withscores 1) "Chevrolet" 2) "10" 3) "GMC" 4) "20" 5) "Ford" 6) "30" # Изменение весов элементов 127.0.0.1:6379> zadd manufacturers 30 Chevrolet 10 GMC 20 Ford (integer) 0 # количество добавленных элементов, было бы 3 при исопльзовании аргумента ch # Содержимое множества 127.0.0.1:6379> zrange manufacturers 0 -1 withscores 1) "GMC" 2) "10" 3) "Ford" 4) "20" 5) "Chevrolet" 6) "30" # Увеличение веса элемента Ford на 20 127.0.0.1:6379> zadd manufacturers incr 20 Ford "40" # Итоговый вес # Содержимое множества 127.0.0.1:6379> zrange manufacturers 0 -1 withscores 1) "GMC" 2) "10" 3) "Chevrolet" 4) "30" 5) "Ford" 6) "40" |
zcard <key>— получение количества элементов множества
|
1 2 |
127.0.0.1:6379> zcard manufacturers (integer) 3 # количество элементов |
zcount <key> <score-min> <score-max>— получение количества элементов множества в указанном диапазоне весов. Границы диапазона указываются включительно.
|
1 2 |
127.0.0.1:6379> zcount manufacturers 10 30 (integer) 2 # количество элементов |
zrange <key> <start> <stop> <byscore | bylex> <rev> <limit offset count> <withscores>— получение элементов множества. Аргументы операции:startиstop— диапазон элементов множества, числа если используется сортировка по весу, иначе элементы списка с ведущей[или(для указания включения или исключения элемента в диапазоне, либо- +— для использования всего диапазона.byscore | bylex— сортировка по весу или алфавитному порядкуrev— получение элементов в обратном порядкеlimit offset count— дополнительное ограничение получаемого подмножестваwithscores— возврат элементов с весами (если не указан аргументbylex)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# Вывод элементов множества с сортировкой по весу 127.0.0.1:6379> zrange manufacturers 0 -1 1) "GMC" 2) "Chevrolet" 3) "Ford" # Вывод элементов множества и их веса с сортировкой по весу 127.0.0.1:6379> zrange manufacturers 0 -1 withscores 1) "GMC" 2) "10" 3) "Chevrolet" 4) "30" 5) "Ford" 6) "40" # Вывод элементов множества до GMC (исключительно) с сортировкой по алфавиту 127.0.0.1:6379> zrange manufacturers - ("GMC" bylex 1) "Chevrolet" 2) "Ford" # Вывод элементов множества после Ford (включительно) с сортировкой по алфавиту 127.0.0.1:6379> zrange manufacturers ["Ford" + bylex 1) "Ford" 2) "GMC" # Вывод всех элементов множества с сортировкой по алфавиту 127.0.0.1:6379> zrange manufacturers - + bylex 1) "Chevrolet" 2) "Ford" 3) "GMC" |
zrank <key> <member> <withscore>— получение позиции элемента во множестве
|
1 2 3 4 5 6 |
127.0.0.1:6379> zrank manufacturers GMC (integer) 0 127.0.0.1:6379> zrank manufacturers GMC withscore 1) (integer) 0 2) "10" |
Итого
В данной статье я вкратце рассказал о том, что такое Redis, описал наиболее используемые типы данных и основным операции с ними. В будущих статьях каждый тип данных будет рассмотрен более подробно, а так же будет описана работа с Redis в проектах на Java.
