wiki/HowtoRedis.md
2017-07-21 11:41:01 +02:00

492 lines
12 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Howto Redis
Redis 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.
<http://redis.io/documentation>
## Installation
*Sous Debian Jessie*, la version de Redis est 2.8.17 :
~~~
# apt install redis-server
~~~
Si on utilise systemd, 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 linstance :
~~~
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.
#### Unite systemd
Créer lunité 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
~~~