====== Шпаргалка по Redis ====== Про Redis ([[http://redis.io/|официальный сайт]], [[http://habrahabr.ru/search/?q=redis|материалы на Хабре]]) написано много, но мне до сего дня не хватало материала, который послужил бы шпаргалкой по его практическому использованию, а так же справочником по базовым теоретическим моментам. Постараюсь заполнить этот пробел в богатой базе знаний Хабра.\\ \\ Я поставил перед собой цель показать возможности Redis с помощью примеров кода. После публикации приму любые предложения по улучшению материала.\\ \\ Здесь используется общение с сервером через консольный клиент, но, основываясь на приведенных примерах, можно легко найти реализацию этих примеров в клиентских библиотеках на вашем любимом языке.\\ \\ === Ключи === \\ Redis — хранилище данных в формате «ключ-значение». Факты о ключах:\\ * Ключи в Redis — бинарно-безопасные ([[http://en.wikipedia.org/wiki/Binary-safe|binary safe]]) строки. * Слишком длинные ключи — плохая идея, не только из-за занимаемой памяти, но так же и в связи с увеличением времени поиска определенного ключа в множестве в связи с дорогостоящим сравнением. * Хорошая идея — придерживаться схемы при построении ключей: «object-type:id:field». \\ \\ === Типы данных Redis === \\ * **Строки** (strings). Базовый тип данных Redis. Строки в Redis бинарно-безопасны, //могут использоваться так же как числа,// ограничены размером 512 Мб. * **Списки** (lists). Классические списки строк, упорядоченные в порядке вставки, которая возможна как со стороны головы, так и со стороны хвоста списка. Максимальное количество элементов — 232 — 1. * **Множества** (sets). Множества строк в математическом понимании: не упорядочены, поддерживают операции вставки, проверки вхождения элемента, пересечения и разницы множеств. Максимальное количество элементов — 232 — 1. * **Хеш-таблицы** (hashes). Классические хеш-таблицы или ассоциативные массивы. Максимальное количество пар «ключ-значение» — 232 — 1. * **Упорядоченные множества** (sorted sets). Упорядоченное множество отличается от обычного тем, что его элементы упорядочены по особому параметру «score». \\ Про типы данных Redis есть отдельная хорошая статья: [[http://habrahabr.ru/post/144054/|«Структуры данных, используемые в Redis»]].\\ \\ \\ === Базовые операции === \\ В консоли для общения с Redis используется клиентская программа ''redis-cli''. Рассмотрим базовые операции.\\ \\ **Задача 1,** создание, выборка, модификация, удаление и базовая информация об объектах.\\ Установить и прочитать значения с ключами вида ''test:1:*''. Узнать тип значения, проверить существование элемента, извлечь все поля записи ''test:1'', удалить поле записи ''test:1''.\\ \\ redis 127.0.0.1:6379> set test:1:string "my binary safe string" OK redis 127.0.0.1:6379> get test:1:string "my binary safe string" redis 127.0.0.1:6379> getset test:1:string "other value" "my binary safe string" redis 127.0.0.1:6379> type test:1:string string redis 127.0.0.1:6379> set test:1:vlaue "487" OK redis 127.0.0.1:6379> rename test:1:vlaue test:1:value OK redis 127.0.0.1:6379> exists test:1:vlaue (integer) 0 redis 127.0.0.1:6379> exists test:1:value (integer) 1 redis 127.0.0.1:6379> keys test:1:* 1) "test:1:string" 2) "test:1:value" redis 127.0.0.1:6379> del test:1:value (integer) 1 redis 127.0.0.1:6379> keys test:1:* 1) "test:1:string" \\ Подробности о командах, связанных с этой задачей можно найти в документации в разделах [[http://redis.io/commands#generic|Keys]] и [[http://redis.io/commands#string|Strings]].\\ \\ **Задача 2,** время жизни объекта.\\ \\ redis 127.0.0.1:6379> ttl test:1:string (integer) -1 redis 127.0.0.1:6379> expire test:1:string 6000 (integer) 1 redis 127.0.0.1:6379> ttl test:1:string (integer) 5997 \\ По умолчанию объект не ограничен временем жизни, поэтому ''TTL'' возвращает -1, после установки значения командой ''EXPIRE'' команда ''TTL'' уже возвращает оставшееся количество секунд.\\ \\ Подробности о командах, связанных с этой задачей можно найти в документации в разделах [[http://redis.io/commands#generic|Keys]] и [[http://redis.io/commands#string|Strings]].\\ \\ **Задача 3,** pipelining, выполнение нескольких команд одним запросом.\\ \\ PS D:\Programs\Redis\64bit> "set test:1:pvalue 'test'`r`nget test:1:pvalue" | .\redis-cli OK "test" \\ Pipelining удобно использовать для оптимизации массовых вставок.\\ \\ **Задача 4,** транзакции.\\ Для реализации транзакций в Redis используются следующие основные команды:\\ * ''MULTI'' — начать запись команд для транзакции. * ''EXEC'' — выполнить записанные команды. * ''DISCARD'' — удалить все записанные команды. * ''WATCH'' — команда, обеспечивающая поведение типа «check-and-set» (CAS) — транзакция выполняется только в случае, если другие клиенты не изменили значение переменной. Иначе ''EXEC'' не выполнит записанные команды. \\ redis 127.0.0.1:6379> multi OK redis 127.0.0.1:6379> set test:1:trValue "1" QUEUED redis 127.0.0.1:6379> incr test:1:trValue QUEUED redis 127.0.0.1:6379> decr test:1:trValue QUEUED redis 127.0.0.1:6379> exec 1) OK 2) (integer) 2 3) (integer) 1 \\ Подробности о командах, связанных с этой задачей можно найти в документации в разделе [[http://redis.io/topics/transactions|Transactions]].\\ \\ === Строки/числа === \\ **Задача 5,** продемонстрировать основные строковые операции.\\ \\ redis 127.0.0.1:6379> set test:1:string "hello" OK redis 127.0.0.1:6379> append test:1:string " world!" (integer) 12 redis 127.0.0.1:6379> get test:1:string "hello world!" redis 127.0.0.1:6379> strlen test:1:string (integer) 12 redis 127.0.0.1:6379> getrange test:1:string 6 10 "world" redis 127.0.0.1:6379> setrange test:1:string 6 "habrahabr!" (integer) 16 redis 127.0.0.1:6379> get test:1:string "hello habrahabr!" \\ \\ **Задача 6,** продемонстрировать операции над числами.\\ \\ redis 127.0.0.1:6379> set test:1:int 1 OK redis 127.0.0.1:6379> incr test:1:int (integer) 2 redis 127.0.0.1:6379> decr test:1:int (integer) 1 redis 127.0.0.1:6379> incrby test:1:int 20 (integer) 21 redis 127.0.0.1:6379> decrby test:1:int 15 (integer) 6 \\ Подробности о командах, связанных с этими задачами можно найти в документации в разделе [[http://redis.io/commands#string|Strings]].\\ \\ === Списки === \\ **Задача 7,** создать список, продемонстрировать основные операции над списками.\\ \\ redis 127.0.0.1:6379> rpush test:1:messages "Hello, world!" (integer) 1 redis 127.0.0.1:6379> rpush test:1:messages "Hello, user!" (integer) 2 redis 127.0.0.1:6379> rpush test:1:messages "Wow!" (integer) 3 redis 127.0.0.1:6379> lrange test:1:messages 0 2 1) "Hello, world!" 2) "Hello, user!" 3) "Wow!" redis 127.0.0.1:6379> llen test:1:messages (integer) 3 redis 127.0.0.1:6379> lpop test:1:messages "Hello, world!" redis 127.0.0.1:6379> lpop test:1:messages "Hello, user!" redis 127.0.0.1:6379> lpop test:1:messages "Wow!" redis 127.0.0.1:6379> llen test:1:messages (integer) 0 \\ Подробности о командах, связанных с этой задачей можно найти в документации в разделе [[http://redis.io/commands#list|Lists]].\\ \\ === Множества, упорядоченные множества === \\ **Задача 8,** создать множество, продемонстрировать основные операции над множествами.\\ \\ redis 127.0.0.1:6379> sadd test:1:fruits "banana" (integer) 1 redis 127.0.0.1:6379> sadd test:1:fruits "apple" (integer) 1 redis 127.0.0.1:6379> sadd test:1:fruits "strawberry" (integer) 1 redis 127.0.0.1:6379> sadd test:1:yellowThings "banana" (integer) 1 redis 127.0.0.1:6379> sadd test:1:yellowThings "apple" (integer) 1 redis 127.0.0.1:6379> sadd test:1:redThings "strawberry" (integer) 1 redis 127.0.0.1:6379> scard test:1:fruits (integer) 3 redis 127.0.0.1:6379> sdiff test:1:fruits test:1:yellowThings 1) "strawberry" redis 127.0.0.1:6379> sdiffstore test:1:noYellowFruits test:1:fruits test:1:yellowThings (integer) 1 redis 127.0.0.1:6379> sinter test:1:yellowThings test:1:fruits 1) "banana" 2) "apple" redis 127.0.0.1:6379> sismember test:1:fruits "banana" (integer) 1 redis 127.0.0.1:6379> sismember test:1:fruits "tomato" (integer) 0 redis 127.0.0.1:6379> smembers test:1:noYellowFruits 1) "strawberry" redis 127.0.0.1:6379> smove test:1:yellowThings test:1:redThings "apple" (integer) 1 redis 127.0.0.1:6379> smembers test:1:redThings 1) "strawberry" 2) "apple" redis 127.0.0.1:6379> spop test:1:redThings "apple" redis 127.0.0.1:6379> srandmember test:1:fruits "apple" redis 127.0.0.1:6379> srem test:1:fruits "banana" (integer) 1 redis 127.0.0.1:6379> sunion test:1:yellowThings test:1:redThings 1) "strawberry" 2) "banana" redis 127.0.0.1:6379> sunionstore test:1:allThings test:1:yellowThings test:1:redThings (integer) 2 redis 127.0.0.1:6379> smembers test:1:allThings 1) "strawberry" 2) "banana" \\ Подробности о командах, связанных с этой задачей можно найти в документации в разделе [[http://redis.io/commands#set|Sets]].\\ \\ **Задача 9,** создать упорядоченное множество и продемонстрировано основные операции над ним.\\ В упорядоченном множестве элементы сравниваются по дополнительному параметру «score».\\ \\ redis 127.0.0.1:6379> zadd hackers 1953 "Richard Stallman" (integer) 1 redis 127.0.0.1:6379> zadd hackers 1940 "Alan Kay" (integer) 1 redis 127.0.0.1:6379> zadd hackers 1965 "Yukihiro Matsumoto" (integer) 1 redis 127.0.0.1:6379> zadd hackers 1916 "Claude Shannon" (integer) 1 redis 127.0.0.1:6379> zadd hackers 1969 "Linus Torvalds" (integer) 1 redis 127.0.0.1:6379> zadd hackers 1912 "Alan Turing" (integer) 1 redis 127.0.0.1:6379> zrange hackers 0 -1 1) "Alan Turing" 2) "Claude Shannon" 3) "Alan Kay" 4) "Richard Stallman" 5) "Yukihiro Matsumoto" 6) "Linus Torvalds" redis 127.0.0.1:6379> zrevrange hackers 0 -1 1) "Linus Torvalds" 2) "Yukihiro Matsumoto" 3) "Richard Stallman" 4) "Alan Kay" 5) "Claude Shannon" 6) "Alan Turing" redis 127.0.0.1:6379> zrangebyscore hackers -inf 1950 1) "Alan Turing" 2) "Claude Shannon" 3) "Alan Kay" redis 127.0.0.1:6379> zremrangebyscore hackers 1940 1960 (integer) 2 redis 127.0.0.1:6379> zrange hackers 0 -1 1) "Alan Turing" 2) "Claude Shannon" 3) "Yukihiro Matsumoto" 4) "Linus Torvalds" \\ Подробности о командах, связанных с этой задачей можно найти в документации в разделе [[http://redis.io/commands#sorted_set|Sorted sets]].\\ \\ === Хеш-таблицы === \\ **Задача 10,** Создать хеш-таблицу и продемонстрировать основные операции над хешами.\\ \\ redis 127.0.0.1:6379> hset users:1 name "Andrew" (integer) 1 redis 127.0.0.1:6379> hset users:1 email "andrew@example.com" (integer) 1 redis 127.0.0.1:6379> hkeys users:1 1) "name" 2) "email" redis 127.0.0.1:6379> hvals users:1 1) "Andrew" 2) "andrew@example.com" redis 127.0.0.1:6379> hgetall users:1 1) "name" 2) "Andrew" 3) "email" 4) "andrew@example.com" redis 127.0.0.1:6379> hset users:1 test 1 (integer) 1 redis 127.0.0.1:6379> hincrby users:1 test 123 (integer) 124 redis 127.0.0.1:6379> hvals users:1 1) "Andrew" 2) "andrew@example.com" 3) "124" redis 127.0.0.1:6379> hdel users:1 test (integer) 1 redis 127.0.0.1:6379> hvals users:1 1) "Andrew" 2) "andrew@example.com" \\ Подробности о командах, связанных с этой задачей можно найти в документации в разделе [[http://redis.io/commands#hash|Hashes]].\\ \\ === Pub/Sub, сообщения в Redis === \\ **Задача 11,** подписаться на сообщения на одном клиенте и отправить сообщение из другого.\\ Приведем окна двух клиентов, в первом окне совершается подписка на сообщения и видно отправленное из второго окна сообщение.\\ \\ redis 127.0.0.1:6379> SUBSCRIBE messages Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "messages" 3) (integer) 1 1) "message" 2) "messages" 3) "Hello world!" \\ redis 127.0.0.1:6379> PUBLISH messages "Hello world!" (integer) 1 \\ \\ **Задача 12,** подписаться на сообщения на одном клиенте и отправить сообщение из другого. Подписку осуществить с помощью шаблонов.\\ Приведем окна двух клиентов, в первом окне совершается подписка на сообщения и видно отправленное из второго окна сообщение.\\ \\ redis 127.0.0.1:6379> PSUBSCRIBE news.* Reading messages... (press Ctrl-C to quit) 1) "psubscribe" 2) "news.*" 3) (integer) 1 1) "pmessage" 2) "news.*" 3) "news.art" 4) "New picture!" 1) "pmessage" 2) "news.*" 3) "news.cinema" 4) "New movie!" \\ redis 127.0.0.1:6379> PUBLISH news.art "New picture!" (integer) 1 redis 127.0.0.1:6379> PUBLISH news.cinema "New movie!" (integer) 1