516 lines
12 KiB
Markdown
516 lines
12 KiB
Markdown
---
|
||
categories: databases nosql
|
||
title: Howto Redis
|
||
...
|
||
|
||
* Documentation : <https://redis.io/documentation>
|
||
* Rôle Ansible : <https://forge.evolix.org/projects/ansible-roles/repository/show/redis>
|
||
|
||
|
||
[Redis](https://redis.io/) est un serveur noSQL clé-valeur. Une valeur peut être une chaîne de caractères, un tableau, une liste, etc.
|
||
Redis tourne en mémoire, et sauvegarde de temps en temps ses données sur le disque.
|
||
|
||
|
||
## Installation
|
||
|
||
*Sous Debian Jessie*, la version de Redis est 2.8.17 :
|
||
|
||
~~~
|
||
# apt install redis-server redis-tools
|
||
|
||
$ /usr/bin/redis-server -v
|
||
Redis server v=3.2.6 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=826601c992442478
|
||
|
||
# systemctl status redis
|
||
● redis-server.service - Advanced key-value store
|
||
Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled)
|
||
Docs: http://redis.io/documentation,
|
||
man:redis-server(1)
|
||
Main PID: 3432 (redis-server)
|
||
CGroup: /system.slice/redis-server.service
|
||
└─3432 /usr/bin/redis-server 127.0.0.1:6379
|
||
~~~
|
||
|
||
Si on utilise [systemd](HowtoSystemd), on surcharge l'unité `redis.service` en spécifiant
|
||
le `RuntimeDirectory` (voir la note
|
||
[dans la documentation de la migration Wheezy -> Jessie](HowtoDebian/MigrationWheezyJessie#redis)).
|
||
|
||
|
||
## Configuration
|
||
|
||
La configuration principale se fait dans `/etc/redis/redis.conf` dont voici quelques options :
|
||
|
||
~~~
|
||
daemonize yes
|
||
pidfile /var/run/redis.pid
|
||
port 6379
|
||
unixsocket /var/run/redis/redis.sock
|
||
bind 127.0.0.1
|
||
timeout 300
|
||
loglevel notice
|
||
logfile /var/log/redis/redis-server.log
|
||
databases 16
|
||
save 900 1
|
||
save 300 10
|
||
save 60 10000
|
||
dbfilename dump.rdb
|
||
dir /var/lib/redis
|
||
#requirepass <password>
|
||
maxclients 128
|
||
maxmemory 104857600
|
||
~~~
|
||
|
||
La plupart des options sont reconfigurables en mode CLI via la commande _CONFIG SET_.
|
||
La liste des arguments peut être listée :
|
||
|
||
~~~
|
||
redis> CONFIG get *
|
||
1) "dir"
|
||
2) "/var/lib/redis"
|
||
3) "dbfilename"
|
||
4) "dump.rdb"
|
||
5) "requirepass"
|
||
6) (nil)
|
||
7) "masterauth"
|
||
8) (nil)
|
||
9) "maxmemory"
|
||
10) "0"
|
||
~~~
|
||
|
||
## Utilisation
|
||
|
||
En mode CLI :
|
||
|
||
~~~
|
||
$ redis-cli
|
||
redis 127.0.0.1:6379>
|
||
redis> set foo 3
|
||
OK
|
||
redis> get blabla
|
||
(nil)
|
||
redis> get foo
|
||
3
|
||
redis> keys *
|
||
1) "foo"
|
||
redis> mset un 1 deux 2 trois 3 quatre 4
|
||
OK
|
||
redis> keys *
|
||
1) "un"
|
||
2) "foo"
|
||
3) "deux"
|
||
4) "trois"
|
||
5) "quatre"
|
||
redis> *keys *r*
|
||
1) "four"
|
||
2) "three"
|
||
redis> get four
|
||
"4"
|
||
redis> del "trois" "quatre"
|
||
(integer) 2
|
||
~~~
|
||
|
||
On peut se connecter avec la socket si elle existe :
|
||
|
||
~~~
|
||
$ redis-cli -s /path/to/redis.sock
|
||
~~~
|
||
|
||
Mais aussi en réseau (sans authentification, attention) :
|
||
|
||
~~~
|
||
$ telnet 127.0.0.1 6379
|
||
Trying 127.0.0.1...
|
||
Connected to 127.0.0.1.
|
||
Escape character is '^]'.
|
||
get foo
|
||
$1
|
||
3
|
||
quit
|
||
Connection closed by foreign host.
|
||
~~~
|
||
|
||
En PHP, il existe différentes bibliothèques. Nous utilisons principalement <http://github.com/nicolasff/phpredis>
|
||
et nous utilisons un fork pour avoir un packaging Debian propre :
|
||
|
||
~~~
|
||
$ git clone <https://github.com/gcolpart/phpredis>
|
||
$ cd phpredis
|
||
$ tar --exclude debian --exclude .git -cvzf ../php5-redis_0.1~git20120519.orig.tar.gz .
|
||
$ git-buildpackage -us -uc
|
||
~~~
|
||
|
||
|
||
## Sessions PHP avec Redis
|
||
|
||
Redis peut notamment être utilisé pour stocker les sessions PHP. Par exemple :
|
||
|
||
~~~
|
||
session.save_handler = redis
|
||
session.save_path = "tcp://127.0.0.1:6379?auth=<password>"
|
||
~~~
|
||
|
||
|
||
## Instances Redis
|
||
|
||
Il est possible de faire fonctionner plusieurs instances de Redis sur un serveur ; chacune avec ses propres données, sa propre configuration et son propre utilisateur.
|
||
|
||
### Template systemd
|
||
|
||
Creer le template d'unité systemd suivant dans /etc/systemd/system/redis@.service :
|
||
|
||
~~~
|
||
[Unit]
|
||
Description=Advanced key-value store
|
||
After=network.target
|
||
|
||
[Service]
|
||
ExecStartPre=/bin/mkdir -m 0755 -p /run/redis/%i
|
||
ExecStartPre=/bin/chown redis-%i: /run/redis/%i
|
||
PermissionsStartOnly=yes
|
||
|
||
Type=forking
|
||
PIDFile=/run/redis/%i/redis.pid
|
||
ExecStart=/usr/bin/redis-server /etc/redis/redis-%i.conf --unixsocket /run/redis/%i/redis.sock --pidfile /run/redis/%i/redis.pid
|
||
ExecStop=/usr/bin/redis-cli -s /run/redis/%i/redis.sock shutdown
|
||
Restart=always
|
||
User=redis-%i
|
||
Group=redis-%i
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
~~~
|
||
|
||
Recharger la configuration systemd :
|
||
|
||
~~~
|
||
systemctl daemon-reload
|
||
~~~
|
||
|
||
### Installation
|
||
|
||
Créer un utilisateur système pour l’instance :
|
||
|
||
~~~
|
||
useradd --system --home-dir /var/lib/redis/instance1 redis-instance1
|
||
~~~
|
||
|
||
Créer ensuite le *datadir* et le dossier de log :
|
||
|
||
~~~
|
||
mkdir -m 0750 -p /var/lib/redis/instance1 /var/log/redis/instance1
|
||
chown redis-instance1: /var/lib/redis/instance1 /var/log/redis/instance1
|
||
~~~
|
||
|
||
Créer ensuite le fichier de configuration suivant dans /etc/redis/redis-instance1.conf :
|
||
|
||
~~~
|
||
daemonize yes
|
||
port 0 # Listen only on unix socket defined by systemd unit
|
||
unixsocketperm 770 # Unix socket only accessible by user and group of instance1
|
||
timeout 300
|
||
loglevel notice
|
||
logfile /var/log/redis/instance1/redis-server.log
|
||
databases 16
|
||
save 900 1
|
||
save 300 10
|
||
save 60 10000
|
||
dbfilename dump.rdb
|
||
dir /var/lib/redis/instance1
|
||
#requirepass <password>
|
||
maxclients 128
|
||
maxmemory 104857600
|
||
~~~
|
||
|
||
### Administration
|
||
|
||
L'instance Redis "instance1" est maintenant administrable via :
|
||
|
||
~~~
|
||
systemctl start redis@instance1
|
||
systemctl stop redis@instance1
|
||
systemctl restart redis@instance1
|
||
systemctl status redis@instance1
|
||
systemctl enable redis@instance1
|
||
systemctl disable redis@instance1
|
||
~~~
|
||
|
||
|
||
## Sauvegardes
|
||
|
||
<http://redis.io/topics/persistence>
|
||
|
||
Par défaut, Redis sauvegarde de temps en temps ses données sur le disque (mode RDB persistence).
|
||
Il suffit donc de copier le fichier */var/lib/redis/dump.rdb* pour sauvegarder une base Redis à chaud !
|
||
|
||
Pour restaurer les données, il suffira d'éteindre Redis, remettre en place le fichier RDB, et relancer Redis.
|
||
|
||
|
||
## Réplication
|
||
|
||
<http://redis.io/topics/replication>
|
||
|
||
Côté "slave" il suffit de mettre en place la configuration :
|
||
|
||
~~~
|
||
slaveof 192.0.43.10 6379
|
||
#masterauth <password>
|
||
~~~
|
||
|
||
Une fois le démon relancé on peut vérifier l'état de la réplication de la façon suivante :
|
||
|
||
~~~
|
||
#redis-cli -h X.X.X.X -p 6379 info replication
|
||
~~~
|
||
|
||
On peut arrêter la réplication et passer un slave en master
|
||
|
||
~~~
|
||
#redis-cli -h X.X.X.X -p 6379 slaveof no one
|
||
~~~
|
||
|
||
~~~
|
||
#redis-cli -h X.X.X.X -p 6379 info replication
|
||
# Replication
|
||
role:master
|
||
connected_slaves:1
|
||
master_repl_offset:631177410
|
||
repl_backlog_active:0
|
||
repl_backlog_size:1048576
|
||
repl_backlog_first_byte_offset:630128835
|
||
repl_backlog_histlen:1048576
|
||
~~~
|
||
|
||
### Tests
|
||
|
||
On test une écriture sur le master, est-ce répliqué sur le slave ?
|
||
|
||
|
||
~~~
|
||
redis [master] 127.0.0.1:6379> set key value
|
||
redis [slave] 127.0.0.1:6379> get key
|
||
~~~
|
||
|
||
On devrait avoir « value ». Par ailleurs on pourra lire dans les logs du slave (/var/log/redis/redis-server.log) :
|
||
|
||
~~~
|
||
[26287] 06 Sep 15:04:04 * MASTER <-> SLAVE sync: receiving 34 bytes from master
|
||
~~~
|
||
|
||
Depuis redis 2.6 (2.4 en Wheezy), par défaut, le slave est en read-only, on peut le passer en read & write, en mettant ceci dans la configuration du slave :
|
||
|
||
~~~
|
||
slave-read-only off
|
||
~~~
|
||
|
||
### Sentinel
|
||
|
||
Sentinel permet de faire du failover avec des slaves Redis.
|
||
Attention, il est encore en développement. Il est donc dans la branche instable du dépôt de redis.
|
||
Par ememple, une instance master redis1 et un slave redis2. En cas de panne les rôles s'échangent, redis2 devient master et redis1 devient le slave.
|
||
|
||
#### Unité systemd
|
||
|
||
Créer l’unité systemd suivant dans /etc/systemd/system/redis-sentinel.service :
|
||
|
||
~~~
|
||
[Unit]
|
||
Description=Advanced key-value store (monitoring)
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
PIDFile=/run/redis/sentinel.pid
|
||
ExecStart=/usr/bin/redis-sentinel /etc/redis/sentinel.conf --unixsocket /run/redis/sentinel.sock --pidfile /run/redis/sentinel.pid
|
||
ExecStop=/usr/bin/redis-cli -s /run/redis/sentinel.sock shutdown
|
||
Restart=always
|
||
User=redis
|
||
Group=redis
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
~~~
|
||
|
||
Créer ensuite le fichier de configuration suivant dans /etc/redis/sentinel.conf :
|
||
|
||
~~~
|
||
port 16379
|
||
dir "/tmp"
|
||
sentinel monitor replication1 127.0.0.1 6379 1
|
||
sentinel down-after-milliseconds 1000
|
||
sentinel config-epoch replication1 7
|
||
sentinel leader-epoch replication1 8
|
||
sentinel known-slave replication1 127.0.0.1 6380
|
||
sentinel current-epoch 8
|
||
~~~
|
||
|
||
Sentinel doit pouvoir ecrire dans son fichier de configuration :
|
||
|
||
~~~
|
||
chown redis: /etc/redis/sentinel.conf
|
||
~~~
|
||
|
||
|
||
## Benchmarks
|
||
|
||
<http://redis.io/topics/benchmarks>
|
||
|
||
~~~
|
||
redis-benchmark -n 100000
|
||
=##### PING (inline)=
|
||
100000 requests completed in 1.88 seconds
|
||
50 parallel clients
|
||
3 bytes payload
|
||
keep alive: 1
|
||
|
||
97.82% <= 1 milliseconds
|
||
99.80% <= 2 milliseconds
|
||
99.89% <= 3 milliseconds
|
||
99.93% <= 4 milliseconds
|
||
99.93% <= 5 milliseconds
|
||
100.00% <= 6 milliseconds
|
||
100.00% <= 6 milliseconds
|
||
53276.50 requests per second
|
||
|
||
=##### PING=
|
||
100000 requests completed in 1.97 seconds
|
||
50 parallel clients
|
||
3 bytes payload
|
||
keep alive: 1
|
||
|
||
93.58% <= 1 milliseconds
|
||
99.36% <= 2 milliseconds
|
||
99.61% <= 3 milliseconds
|
||
99.71% <= 4 milliseconds
|
||
99.81% <= 5 milliseconds
|
||
99.87% <= 6 milliseconds
|
||
99.88% <= 7 milliseconds
|
||
99.88% <= 8 milliseconds
|
||
99.92% <= 10 milliseconds
|
||
99.93% <= 11 milliseconds
|
||
99.93% <= 12 milliseconds
|
||
99.95% <= 13 milliseconds
|
||
100.00% <= 13 milliseconds
|
||
50761.42 requests per second
|
||
|
||
=##### MSET (10 keys)=
|
||
100000 requests completed in 3.12 seconds
|
||
50 parallel clients
|
||
3 bytes payload
|
||
keep alive: 1
|
||
|
||
19.71% <= 1 milliseconds
|
||
91.36% <= 2 milliseconds
|
||
98.93% <= 3 milliseconds
|
||
99.66% <= 4 milliseconds
|
||
99.75% <= 5 milliseconds
|
||
99.76% <= 8 milliseconds
|
||
99.77% <= 9 milliseconds
|
||
99.77% <= 10 milliseconds
|
||
99.80% <= 11 milliseconds
|
||
99.80% <= 14 milliseconds
|
||
99.85% <= 15 milliseconds
|
||
99.89% <= 22 milliseconds
|
||
99.89% <= 23 milliseconds
|
||
99.94% <= 24 milliseconds
|
||
99.95% <= 160 milliseconds
|
||
99.95% <= 208 milliseconds
|
||
99.95% <= 245 milliseconds
|
||
99.95% <= 246 milliseconds
|
||
100.00% <= 246 milliseconds
|
||
32020.49 requests per second
|
||
|
||
=##### SET=
|
||
100000 requests completed in 1.86 seconds
|
||
50 parallel clients
|
||
3 bytes payload
|
||
keep alive: 1
|
||
|
||
97.80% <= 1 milliseconds
|
||
99.78% <= 2 milliseconds
|
||
99.84% <= 3 milliseconds
|
||
99.87% <= 4 milliseconds
|
||
99.93% <= 5 milliseconds
|
||
99.95% <= 10 milliseconds
|
||
99.96% <= 11 milliseconds
|
||
100.00% <= 12 milliseconds
|
||
100.00% <= 12 milliseconds
|
||
53850.30 requests per second
|
||
|
||
=##### GET=
|
||
100000 requests completed in 2.02 seconds
|
||
50 parallel clients
|
||
3 bytes payload
|
||
keep alive: 1
|
||
|
||
91.26% <= 1 milliseconds
|
||
99.65% <= 2 milliseconds
|
||
99.86% <= 3 milliseconds
|
||
99.89% <= 4 milliseconds
|
||
99.92% <= 5 milliseconds
|
||
99.97% <= 7 milliseconds
|
||
100.00% <= 7 milliseconds
|
||
49407.12 requests per second
|
||
|
||
[etc.]
|
||
~~~
|
||
|
||
|
||
## Monitoring
|
||
|
||
### En live
|
||
|
||
Voir des stats toutes les secondes :
|
||
|
||
~~~
|
||
$ redis-cli --stat
|
||
------- data ------ --------------------- load -------------------- - child -
|
||
keys mem clients blocked requests connections
|
||
227947 1.25G 21 0 15259436851 (+0) 252707982
|
||
227948 1.25G 22 0 15259437470 (+619) 252708002
|
||
227951 1.25G 20 0 15259438412 (+942) 252708021
|
||
227951 1.25G 18 0 15259438787 (+375) 252708025
|
||
[…]
|
||
~~~
|
||
|
||
Voir les requêtes que redis reçoit :
|
||
|
||
~~~
|
||
$ redis-cli monitor
|
||
~~~
|
||
|
||
### Nagios
|
||
|
||
Un check Nagios « basique » consiste à initier une connexion TCP sur le socket unix du serveur Redis, et s'assurer qu'il répond bien :
|
||
|
||
~~~
|
||
$ /usr/lib/nagios/plugins/check_tcp -H /var/run/redis.pid
|
||
~~~
|
||
|
||
Des checks Nagios avancés existent également, notamment pour surveiller la réplication ou pour retourner diverses info sur le status du serveur :
|
||
|
||
* <http://exchange.nagios.org/directory/Plugins/Others/check_redis/details>
|
||
* <https://github.com/shift/nagios-check-redis/>
|
||
|
||
Ces 2 plugins nécessitent de se connecter via un socket réseau au serveur, mais une [version antérieure](https://github.com/shift/nagios-check-redis/commit/16ee166aecd7b617c21dc8138a61829f506dc34c) de _nagios-check-redis_ supporte les sockets unix.
|
||
|
||
### Munin
|
||
|
||
* Un plugin Munin existe pour grapher divers paramètres comme la mémoire utilisée par Redis, le nombre de clés utiliséees, le nombre de requêtes par seconde, et le nombre de clients connectés.
|
||
|
||
~~~
|
||
# mkdir -p /usr/local/share/munin/plugins/
|
||
# cd /usr/local/share/munin/plugins/
|
||
# wget "https://raw.githubusercontent.com/munin-monitoring/contrib/master/plugins/redis/redis_"
|
||
# chmod -R 755 /usr/local/share/munin
|
||
# cd /etc/munin/plugins/
|
||
# for module in connected_clients key_ratio keys_per_sec per_sec used_keys used_memory; do ln -s /usr/local/share/munin/plugins/redis_ redis_${module}; done
|
||
~~~
|
||
|
||
Si vous avez un mot de passe à votre redis :
|
||
|
||
~~~
|
||
# cat /etc/munin/plugin-conf.d/munin-node
|
||
[redis_*]
|
||
env.password PASSWORD
|
||
~~~
|