Couverture de l'article Tuto Redis : Le cluster redis 3.0
Retour aux articles

L'agence

WanadevStudio

Tuto Redis : Le cluster redis 3.0

Redis est un moteur de base de données clé-valeur léger, rapide et persistant. Suivez le guide pour améliorer ses performances grâce à Redis Cluster !

Très utilisée par de nombreux acteurs web tels que GitHub, Instagram, Tumblr ou Twitter, cette solution développée en C souffrait de l’absence d’un mode cluster pour rivaliser avec la concurrence et ainsi gérer un service HA (haute disponibilité).

Des alternatives existent telles que Sentinel, disRedis pour basculer automatiquement un serveur maître (master) défaillant sur une instance esclave (slave). La mise en œuvre de ces outils est parfois complexe et ne propose pas une vraie gestion de cluster pour un environnement "scalable".

Une des principales caractéristiques de Redis est de conserver l'intégralité des données en RAM. Cela permet d'obtenir d'excellentes performances en évitant les accès disques, particulièrement coûteux.

Depuis plusieurs mois, Salvatore Sanfilippo le créateur de Redis et les nombreux contributeurs du projet travaillent sur une v3 avec comme nouvelle fonctionnalité principale une prise en charge native du cluster. Cette version étant maintenant stable et disponible depuis le 1er avril, c’est l’occasion pour nous de regarder son fonctionnement d'un peu plus près.

Fonctionnement du cluster

La vraie puissance du cluster à la sauce Redis 3, c’est de pouvoir combiner le partage des données entre nodes et une gestion automatique des défaillances (failover).

Pour comprendre le cluster, vous devez savoir que Redis fonctionne sur le principe du node. Un node est une instance Redis server qui utilise deux ports : un port de communication classique pour pouvoir échanger avec un client Redis et un port spécifique (cluster bus port) qui gère la communication entre les nodes. Ce dernier est obtenu en ajoutant 10000 au port du node. (port redis : 7000, cluster bus : 17000).

En mode cluster, un node se voit attribuer un hash slot (une part des données) du cluster. Un cluster contient 16384 hashs repartis sur les différents nodes utilisés.

Le but est de pouvoir découpler la quantité des données stockées pour le répartir sur plusieurs machines.

Ce partage est effectué à partir d’un calcul utilisant la clé de stockage. Redis est une technologie performante, mais qui nécessite rapidement beaucoup de mémoire. Ce sharing (partage) des données va permettre de partager la charge et la consommation sur plusieurs serveurs.

crédit photo : www.stechfrites.com

Pour commencer un cluster, Redis préconise l’utilisation de 3 nodes (A, B et C). Dans notre cas notre cluster sera déployé sur 3 serveurs. Par défaut, chaque node est démarré en master.

En cas de défaillance d’un des deux serveurs, nous perdons les nodes qui étaient hébergés et donc une partie des données. Pire, dans ce cas-là, le cluster perd son intégrité et ne peut plus fonctionner. Il est donc nécessaire d’utiliser l’option Replica pour permettre d’allouer un slave (A1, B1, C1) pour chaque master créé.

Le principe du slave est de répliquer les données du master. Le cluster Redis va ensuite gérer automatiquement les défaillances d’un node master en promulguant le slave associé. Dans ce cas-là, aucune donnée n’est perdue et le service reste disponible!

Lancement de votre premier cluster

En prérequis, vous devez avoir installé sur vos trois machines Linux : build-essential, ruby, ruby-dev et rubygems. Récupérez Redis et installez le :

$ wget http://download.redis.io/releases/redis-3.0.0.tar.gz
$ tar xzf redis-3.0.0.tar.gz
$ cd redis-3.0.0
$ make

Nos serveurs ont comme adresse 10.0.2.10, 10.0.2.42, 10.0.2.43 et nos nodes auront comme port 7000, 7001. La première étape consiste à créer les nodes sur chaque serveur. Nous allons d'abord créer les dossiers par instance :

$ mkdir 7000 7001

puis exécuter la création des instances redis :

$ ./redis-server --port 7000 --cluster-enabled yes --dir 7000 --cluster-config-file nodes.conf --cluster-node-timeout $TIMEOUT --appendonly yes --appendfilename appendonly.aof --dbfilename dump.rdb --logfile redis.log --daemonize yes
$ ./redis-server --port 7001 --cluster-enabled yes --dir 7001 --cluster-config-file nodes.conf --cluster-node-timeout $TIMEOUT --appendonly yes --appendfilename appendonly.aof --dbfilename dump.rdb --logfile redis.log --daemonize yes

On note que sur ces commandes, les nodes seront lancés avec une gestion AOF (appendonly) qui permet d'éviter des pertes de données en cas de crash.

Le script va aussi créer des fichiers de configuration et les espaces de stockage dans le dossier de chaque port créé précédemment.

Une fois vos 6 nodes démarrés (2 nodes par serveur), nous allons exécuter la commande de mise en cluster de ces instances. Nous utiliserons « redis-trib » développé en ruby qui permet de gérer la sharding et les connexions entre les nodes.

$ ./redis-trib.rb create --replicas 1  10.0.2.41:7000 10.0.2.42:7000 10.0.2.43:7000 10.0.2.41:7001 10.0.2.42:7001 10.0.2.43:7001

À ce moment-là, redis va vous décrire la répartition du cluster (les hashs et les M/S). Les trois premiers nodes de la commandes sont les masters et les 3 derniers sont les slaves. Dans notre cas, chaque serveur aura 1 master et 1 slave d'un autre node.

Une fois votre cluster créé, il deviendra complètement autonome. Ainsi si vous arrêtez redis sur les deux serveurs et que vous les redémarrez ensuite, ils démarreront automatiquement le cluster au même moment. Si vous souhaitez ajouter ou supprimer un node, l'opération devient donc plus lourde (voir "Pour aller plus loin").

Green ?

Maintenant, vérifions l'état de notre cluster :

$ ./redis-cli -p 7000 -h 10.0.2.41 cluster nodes | head -30
86daa6dfb47010e7e3b0e3defd8f61bbcba13c50 10.0.2.42:7000 master - 0 1428995099566 2 connected 5461-10922
e915e680c678037575410dfd3f4377da0bbca8c3 10.0.2.42:7001 slave 3d7821f6693dd7af20903de328126040ef271faa 0 1428995100067 5 connected
f6cc14a662348c208b757571b9725a364ea2e521 10.0.2.43:7001 slave ebed1b997c21921350b1065aefa3e39fabb3876e 0 1428995099766 6 connected
ebed1b997c21921350b1065aefa3e39fabb3876e 10.0.2.43:7000 master - 0 1428995099766 3 connected 10923-16383
2e44642dfc57854fb0e294de2df015428936b4fc 10.0.2.41:7001 slave 86daa6dfb47010e7e3b0e3defd8f61bbcba13c50 0 1428995100067 4 connected
3d7821f6693dd7af20903de328126040ef271faa 10.0.2.41:7000 myself,master - 0 0 1 connected 0-5460

La configuration est correcte et les nodes sont connectés. Le cluster est complètement GREEN !

Nous allons maintenant simuler une défaillance et vérifier que le cluster et les données restent disponibles.

Nous allons tout d'abord ajouter une donnée et la lire depuis le cluster :

10.0.2.41:7000> set moulti pass
OK
10.0.2.41:7000> get moulti
"pass"

Maintenant, nous allons couper l'un des trois serveurs (10.0.2.41) et vérifier l'état du cluster :

3d7821f6693dd7af20903de328126040ef271faa 10.0.2.41:7000 slave,fail e915e680c678037575410dfd3f4377da0bbca8c3 1428998233963 1428998233163 8 disconnected
86daa6dfb47010e7e3b0e3defd8f61bbcba13c50 10.0.2.42:7000 myself,master - 0 0 9 connected 5461-10922
f6cc14a662348c208b757571b9725a364ea2e521 10.0.2.43:7001 slave ebed1b997c21921350b1065aefa3e39fabb3876e 0 1428998244680 6 connected
ebed1b997c21921350b1065aefa3e39fabb3876e 10.0.2.43:7000 master - 0 1428998244580 3 connected 10923-16383
2e44642dfc57854fb0e294de2df015428936b4fc 10.0.2.41:7001 master,fail - 1428998233963 1428998233163 7 disconnected
e915e680c678037575410dfd3f4377da0bbca8c3 10.0.2.42:7001 master - 0 1428998244580 8 connected 0-5460

Nous observons que le master et le slave du serveur 10.0.2.41 sont en échec. Pour le slave rien de problématique, le master du node "e915e680c678037575410dfd3f4377da0bbca8c3" assure le service. En revanche, pour le master qui était sur le serveur éteint, le basculement en failover a fonctionné et le node "86daa6dfb47010e7e3b0e3defd8f61bbcba13c50" a été promulgué (il a devenu master et a récupéré les hashs slots).

Vérifions que notre cluster fonctionne :

10.0.2.42:7001> get moulti
"pass"

Si on redémarre maintenant les nodes sur le serveur 10.0.2.41, les nodes seront en slave. Il nous faut donc  basculer basculer le bon slave en master avec la commande (à exécuter sur le slave) :

CLUSTER FAILOVER FORCE

Pour aller plus loin avec Redis 3.0

Vous devez toujours être vigilant en manipulant votre cluster car certaines opérations ont des conséquences sur le bon fonctionnement sur celui-ci.

Par exemple, la suppression de node oblige le cluster à revoir sa répartition des clés en déplaçant à la volée les données entre nodes. Ce "resharding" est complexe et lourd en ressources système.

Vous devez savoir que le Cluster Redis ne gère pas d'IP failover. Ainsi, vous devez prévoir côté client une gestion multi IP pour pouvoir basculer sur un host fonctionnel en cas de défaillance du premier. Un node ne peut pas accéder et ajouter des données disponible sur un autre node. En revanche il renvoit le node associé. C'est au client Redis de le gérer.

Lors de la conception d'un cluster Redis, si un de vos serveurs devient indisponible, vous devez avoir une majorité de master fonctionnels. En effet, en cas de failover, les master votent pour enclencher le basculement d'un ou des slaves.

Au quotidien, certaines manipulations peuvent être contraignantes pour instancier, démarrer et gérer votre cluster. Il est donc recommandé de passer par un script Bash pour automatiser tout cela. Je vous recommande de partir du script "create-cluster" disponible dans le dossier Utils de Redis.

Si vous souhaitez ensuite utiliser redis pour un projet PHP, vous pourrez passer par différents clients comme redis-php, ou predis.

Des questions sur Redis Cluster ?

Si vous avez des questions sur cet article ou sur Redis 3.0 en général, nous vous invitons à nous les poser en commentaires ci-dessous. Nous nous ferons un plaisir d'en discuter avec vous !

Aussi, tenez-vous au courant de nos futures publications en vous abonnant à Wanadev sur les réseaux sociaux : Wanadev sur Twitter, Wanadev sur Facebook, ainsi que Wanadev sur Google+.

Commentaires

Photo de jeremie auteur du commentaire

jeremie

Il y a 9 ans

je viens de comprendre le node.conf…. désolé
Bonne nouvelle ! Bon courage pour la suite de votre implémentation Redis Cluster.
Bonjour,

J’aimerais savoir si Redis 3.0 exploite maintenant plusieurs processeurs sur la même machine ou s’il faut encore lancer plusieurs instances de Redis sur les gros serveurs pour exploiter leur capacité.

Et aussi, est-ce que les slaves servent seulement à faire une copie de sécurité des données au cas où le maître disparaisse, ou bien est-ce qu’on peut aussi mettre plusieurs slaves pour répartir les lectures quand 1 seul Redis ne suffit pas ?

Y aurait-il un mécanisme quand Redis est surchargé qui pourrait détecter automatiquement les clés utlisées de façon trop intensive et ajuster le nombre de copies en fonction de la fréquence des lectures ?

Merci beaucoup !

Olivier
Bonjour,
Redis3 ne gère pas le multithreading. Il exploite donc un seul processeur par instance. Il est donc fortement conseillé d’utiliser en mode cluster un environnement virtualisé ou des containers avec 1 processeur par machine/container.
Plus vous aurez des nœuds plus la lecture sera découplée. Vous pouvez aussi utiliser les slaves en lecture des données.
Photo de toma perdu auteur du commentaire

toma perdu

Il y a 8 ans

Bonjour,

Merci beaucoup pour votre article, très bien écrit. Je me pose juste une question.
A aucun moment vous parlez de l'utilisation d'un VIP en entré sur Redis. Je m'explique:

entrée -->Redis<--client redis (il vient dépiler redis)


Mon logiciel d'entrée doit taper sur une seule IP, je ne peux pas utiliser sur 3 IP, (les 3 ip correspondant, aux 3 masters) Je dois donc mettre en place un dispositif de Haute Dispo pour envoyer sur les 3 masters en même temps, rectifiez moi, si je me trompe, j'ai peut être mal compris le fonctionnement du cluster redis.

Merci pour votre aide.



Photo de jeremie auteur du commentaire

jeremie

Il y a 9 ans

Bonjour,
Merci pour cet article.
J’essaie d’exécuter les commandes mais il manque le fichier node.conf. Pourriez vous le mettre en ligne?
merci d’avance
Jerem