Redis
Redis — сетевое журналируемое хранилище данных типа «ключ — значение» с открытым исходным кодом.
Хранит ключи в оперативной памяти, снабжена механизмами снимков и журналирования для обеспечения постоянного хранения.
Также предоставляет операции для реализации механизма обмена сообщениями в паттерне publish — subscribe.
Поддерживает репликацию данных с основных узлов на несколько подчинённых (master — slave replication).
Redis работает на большинстве POSIX систем, таких как Linux, *BSD, Mac OS X без каких-либо дополнений.
Linux и Mac OS X — две операционные системы, в которых был разработан и в большей степени протестирован Redis,
поэтому VMware рекомендует использовать именно их для развертывания.
По состоянию на 2011 года, разработка Redis спонсируется компанией VMware.
Имеются клиенты для большого списка языков:
C, C++, C#, Clojure, Lisp, Erlang, Java, JavaScript, Haskell, Lua, Perl, PHP, Python, Ruby, Scala, Go, Tcl, Rust.
Инсталляция
Идем по адресу http://redis.io/download и качаем исходники.
На момент написания этой статьи последняя версия - 2.8.17. Распаковываем архив и запускаем команды:
make
make test
make install
По умолчанию бинарники будут положены в /usr/local/bin. Для того, чтобы redis прописать в автозагрузку,
нужно войти в подкаталог utils и запустить файл install_server.sh. Он задаст вам несколько вопросов, после чего
пропишет все, что нужно:
Port : 6379
Config file : /etc/redis/6379.conf
Log file : /var/log/redis_6379.log
Data dir : /var/lib/redis/6379
Executable : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
После этого можно проверить redis. Запускаем команды:
redis-cli
ping
Типы данных
Redis - это не просто сервер, который хранит пары ключ-знаяение, это сервер, который может хранить произвольные структуры данных.
Список поддерживаемых типов данных:
бинарные строки
списки
сеты
отсортированные сеты
хэши
битовые массивы
логи
Ключ по умолчанию имеет строковый тип.
В качестве ключа можно использовать не просто строки, а бинарные строки. Для оптимального использования строк нужно придерживаться
следующих правил:
длинные ключи - это плохо, например ключ размером в килобайт, поскольку операции с ключами в памяти начнут тормозить
очень короткие ключи - это тоже плохо, например, вместо "u1000flw" лучше использовать "user:1000:followers"
обычно ключ для читабельности состоит из составных частей, разделенных точкой или двоеточием, например "comment:1234:reply.to"
вообще говоря, допустим максимальный размер ключа - аж 512 метров
Для того, чтобы записать что-то в базу или прочитать из базы, используются команды get и set.
Команда set по умолчанию затирает значение, которое уже существует в базе, в противном случае добавляет.
Команде set можно добавить дополнительный параметр - nx либо xx. В первом случае, если в базе уже будет
значение для данного ключа, никакой записи не будет, во втором будет записано новое значение поверх старого.
В redis имеются специальные операторы INCR, INCRBY, DECR, DECRBY., которые делают вычисления над строками,
конвертируя их в числа (redis не хранит числа, но хранит строки, которые могут быть числами):
> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152
Можно за одну операцию сразу записывать или читать несколько ключей - команды MSET, MGET:
> mset a 10 b 20 c 30
OK
> mget a b c
1) "10"
2) "20"
3) "30"
Проверить наличие ключа можно с помощью команды EXISTS., удалить ключ вместе со значением можно командой DEL.:
> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0
Ключу можно задать время жизни - expire - по истечению которого ключ автоматически удаляется.
Время устанавливается в секундах либо миллисекундах:
> set key some-value
OK
> expire key 5
(integer) 1
> get key (immediately)
"some-value"
> get key (after some time)
(nil)
Списки
В redis есть тип данных - список или list. Время вставки элемента в такой список не зависит ни от позиции
в списке, ни от размера самого списка, т.е. это величина постоянная. А вот время доступа к элементу зависит от размера
списка, и чем больше список, тем больше времени. Добавить элемент в список можно командами LPUSH, RPUSH.
Команда LRANGE выделяет диапазон элементов из списка:
> rpush mylist A
(integer) 1
> rpush mylist B
(integer) 2
> lpush mylist first
(integer) 3
> lrange mylist 0 -1
1) "first"
2) "A"
3) "B"
Аналогично можно извлекать элементы из списка с помощью команд LPOP, RPOP
Вообще списки удобно использовать при хранении в таких случаях, как например извлечение выборки
последних десяти изменений. Для этого есть специальная разновидность списков - ограниченные списки,
в которых лишние устаревшие элементы удаляются:
> rpush mylist 1 2 3 4 5
(integer) 5
> ltrim mylist 0 2
OK
> lrange mylist 0 -1
1) "1"
2) "2"
3) "3"
Списки имеют встроенные блокировки, когда с ними работают несколько процессов.
Рассмотрим пример: имеется глобальный список, в который элементы ложатся с помощью команды LPUSH, а забираются командой RPOP.
В этой схеме есть одно узкое место - клиент, который забирает элементы из списка, может обнаружить, что список пуст,
и тогда он начинает долбить базу в бесконечном цикле. Для разрешения этой проблемы есть специальные команды
BRPOP , BLPOP , в которых есть таймаут, по истечению которого они отпускают базу - в следующем случае мы ждем
5 секунд :
brpop tasks 5
Hashe
Хэш - или словарь - это встроенный тип данных, который представляет из себя коллекцию пар ключ-значение:
> hmset user:1000 username antirez birthyear 1977 verified 1
OK
> hget user:1000 username
"antirez"
> hget user:1000 birthyear
"1977"
> hgetall user:1000
1) "username"
2) "antirez"
3) "birthyear"
4) "1977"
5) "verified"
6) "1"
> hmget user:1000 username birthyear no-such-field
1) "antirez"
2) "1977"
3) (nil)
Размер хэша ограничен только размером вашей памяти.
Set
Сет - неотсортированная коллекция уникальных строк.
Вставка, удаление, проверка элемента - по времени константа и не зависит от размера сета.
Добавление элементов:
> sadd myset 1 2 3
(integer) 3
> smembers myset
1. 3
2. 1
3. 2
Проверка:
> sismember myset 3
(integer) 1
> sismember myset 30
(integer) 0
Копирование сета:
sunionstore myset myset2
Получить размер сета:
scard myset
Есть отсортированная разновидность сетов. Рассмотрим пример создания такого сета, где год рождения будет выступать
в роли индекса сортировки:
> zadd hackers 1940 "Alan Kay"
(integer) 1
> zadd hackers 1957 "Sophie Wilson"
(integer 1)
> zadd hackers 1953 "Richard Stallman"
(integer) 1
> zadd hackers 1949 "Anita Borg"
(integer) 1
Тогда извлечение элементов будет в отсортированном порядке:
> zrange hackers 0 -1
4) "Alan Kay"
5) "Anita Borg"
6) "Richard Stallman"
7) "Sophie Wilson"
Чтобы получить список тех, кто родился после 1950:
> zrangebyscore hackers -inf 1950
1) "Alan Kay"
2) "Anita Borg"
Можно удалить хакеров в диапазоне:
zremrangebyscore hackers 1940 1960
Можно получить индекс:
zrank hackers "Anita Borg"
(integer) 4
Можно использовать лексическую индексацию:
zadd hackers 0 "Alan Kay" 0 "Sophie Wilson" 0 "Richard Stallman" 0
"Anita Borg" 0 "Yukihiro Matsumoto" 0 "Hedy Lamarr" 0 "Claude Shannon"
0 "Linus Torvalds" 0 "Alan Turing"
После чего получаем список, отсортированный по алфавиту:
zrange hackers 0 -1
1) "Alan Kay"
2) "Alan Turing"
3) "Anita Borg"
4) "Claude Shannon"
5) "Hedy Lamarr"
6) "Linus Torvalds"
7) "Richard Stallman"
8) "Sophie Wilson"
9) "Yukihiro Matsumoto"
Извлечь в дипазоне по символам
zrangebylex hackers [B [P
1) "Claude Shannon"
2) "Hedy Lamarr"
3) "Linus Torvalds"
|