Aller au contenu

Cluster Cassandra


Créer un cluster Cassandra

La création d'un cluster avec Docker est simple. En effet, pour configurer les noeuds, il existe 2 méthodes :

  • Utiliser des fichiers de configuration cassandra.yaml et les monter comme volumes (avec l'option -v).
  • Utiliser les variables d'environnements (option -e) pour modifier les paramètres de configuration par défaut.

Dans ce quit suit nous utilisons les variables d'environnement dont :

  • CASSANDRA_HOST : nom du noeud ou son adresse IP.
  • CASSANDRA_CLUSTER_NAME : Nom du cluster ququel appartient le noeud.
  • CASSANDRA_SEEDS : les noeuds du cluster Cassandra permettant le démarrage du cluster (bootstrap) contactés par les nouveaux noeuds.
  • CASSANDRA_ENDPOINT_SNITCH : Nom du Snitch (détermine les Racks et Datacenters auxquels apprtiennent les noeuds). Par défaut SimpleSnitch.
  • CASSANDRA_PASSWORD : Mot de passe pour l'utilisateur. Par défault: cassandra.
  • CASSANDRA_PASSWORD_SEEDER : Un noeud par cluster qui permet de changer le mot de passe lors de l'initialisation.
  • CASSANDRA_NUM_TOKENS : nombre de tokens gérés par un noeud.
  • ...

1⃣ Créer un réseau Docker

docker network create cassandra_network

2⃣ Créer le premier noeud

docker run -d --name cass1 \
  --net=cassandra_network \
  -p 9042:9042 \
  -e CASSANDRA_CLUSTER_NAME=cassandra-cluster \
  -e CASSANDRA_NUM_TOKENS=1 \
  -e CASSANDRA_PASSWORD_SEEDER=yes \
  -e CASSANDRA_PASSWORD=mypassword \
  cassandra:4.0.6

💡 Les noeuds appartenant au même cluster ont le même CASSANDRA_CLUSTER_NAME.

3⃣ Créer 2 autres noeuds

docker run -d --name cass2 \
  --net=cassandra_network \
  -e CASSANDRA_CLUSTER_NAME=cassandra-cluster \
  -e CASSANDRA_NUM_TOKENS=1 \
  -e CASSANDRA_SEEDS=cass1 \
  -e CASSANDRA_PASSWORD=mypassword \
  cassandra:4.0.6
docker run -d --name cass3 \
  --net=cassandra_network \
  -e CASSANDRA_CLUSTER_NAME=cassandra-cluster \
  -e CASSANDRA_NUM_TOKENS=1 \
  -e CASSANDRA_SEEDS=cass1 \
  -e CASSANDRA_PASSWORD=mypassword \
  cassandra:4.0.6

💡 Maintenant, vous avez un cluster de 3 noeuds.

Surveillance du cluster

1⃣ Vérifier l'état du cluster

docker exec cass1 nodetool status
2⃣ Voir la répartition des tokens

docker exec cass1 nodetool ring
3⃣ Récupérer les statitiques sur les tables

docker exec cass1 nodetool tablestats
JMX

Cassandra est compatible avec JMX. Un standard qui permet de publier des métriques sur l'utilisation des ressources par Cassandra.

Des outils VisualVM permettent de visualiser ces mesures. Toutefois, il faut préparer le container Docker pour une connexion externe JMX. Avec docker 1. Créer un fichier jmxremote.password contenant une ligne : controlRole jmxpassword 2. Démarrer le container avec la commande

docker run --name containerized-cassandra -p 7199:7199 -v jmxremote.password:/etc/cassandra/jmxremote.password -e LOCAL_JMX='no' cassandra:4.0.6
3. Se connecter avec VisualVM sur localhost:7199 avec les paramètres d'authentification controlRole et jmxpassword

Mise en oeuvre de la réplication

1⃣ Se connecter à un noeud du cluster avec cqlsh

docker exec -it cass1 cqlsh

2⃣ Créer un Keyspace avec un facteur de réplication de 3 et insérer des données

CREATE KEYSPACE IF NOT EXISTS test_replication
WITH REPLICATION = { 'class' :'SimpleStrategy', 'replication_factor': 3};
USE test_replication;
CREATE TABLE cours (
  id INT,
  nom VARCHAR,
  coefficient FLOAT,
  PRIMARY KEY (id)
);
INSERT INTO cours(id, nom, coefficient) VALUES (1, 'NoSQL',1.5);

3⃣ Vérifier la réplication des lignes : Afficher les noeuds ayant une copie du cours 1

docker exec cass1 nodetool getendpoints test_replication cours 1
💡 pour un facteur de réplication 3, 3 noeuds différents doivent être affichés

5⃣ Vérifier les écritures

docker exec cass1 nodetool cfstats test_replication
docker exec cass2 nodetool cfstats test_replication
docker exec cass3 nodetool cfstats test_replication
💡 La valeur de Write Count doit être égale à 1 pour trois noeuds consécutifs sur l'anneau et 0 pour les autres.

6⃣ Vérifier la disponibilité des données à partir de tous les noeuds Se connecter à un noeud avec Write Count égal à 0 et accéder aux données. Si cass3 ne contient pas les noeuds :

docker exec -it cass3 cqlsh
puis

USE test_replication;
SELECT * FROM cours;
Réparer l'état de réplication

Pour forcer la synchronisation des données d'un Keyspace :

docker exec cass1 nodetool repair test_replication

Mise en oeuvre du Sharding

1⃣ Vérifier les token attribué aux noeuds du cluster

docker exec cass1 nodetool ring

Un résultat possible est comme l'aperçu suivant :

root@ab7a361c7e9b:/# nodetool ring

Datacenter: datacenter1
==========
Address          Rack        Status State   Load            Owns                Token                                       
                                                                                6081392343852191785                         
172.26.0.2       rack1       Up     Normal  96.15 KiB       63.08%              -5126891207358132333                        
172.26.0.4       rack1       Up     Normal  139.66 KiB      76.16%              1683513220770616142                         
172.26.0.3       rack1       Up     Normal  96.06 KiB       60.76%              6081392343852191785  

💡 Les noeuds de l'anneau virtuel sont 172.26.0.2 (cass1) puis 172.26.0.4 (cass3) et 172.26.0.3 (cass2) ayant respectivement les tokens -5126891207358132333, 1683513220770616142 et 1683513220770616142

Adresse IP

Pour obtenir l'adresse IP du container cass1

docker exec cass1 ip addr
ou
docker inspect -f '{{ .NetworkSettings.Networks.cassandra_network.IPAddress }}' cass1

2⃣ Insérer d'autres lignes

docker exec -it cass1 cqlsh

puis

USE test_replication;
INSERT INTO cours(id, nom, coefficient) VALUES (10, 'Python',1);
INSERT INTO cours(id, nom, coefficient) VALUES (100, 'Statistiques',1.5);

3⃣ Afficher les tokens des données insérées

select token(id), id from test_replication.cours;
 system.token(id)     | id
----------------------+-----
 -6715243485458697746 |  10
 -4069959284402364209 |   1
  2008715943680221220 | 100

(3 rows)

💡 En examinant les valeurs, l'affectation des lignes selin l'id (clé primaire) aux noeuds du cluster est obtenu ainsi :

  • token(1) = -4069959284402364209 dans ]-5126891207358132333, 1683513220770616142[ ==> noeud 172.26.0.4
  • token(10) = -6715243485458697746 < -5126891207358132333 ==> noeud 172.26.0.2
  • token (100) = 2008715943680221220 dans ]1683513220770616142, 6081392343852191785[ ==> noeud 172.26.0.3

4⃣ Sharding et replication

Vu que la réplication est aussi activée alors chaque ligne est répliquée dans le noeud suivant sur l'anneau.

docker exec -it cass1 bash
root@ab7a361c7e9b:/# nodetool getendpoints test_replication cours 1
172.26.0.4
172.26.0.3
root@ab7a361c7e9b:/# nodetool getendpoints test_replication cours 10
172.26.0.2
172.26.0.4
root@ab7a361c7e9b:/# nodetool getendpoints test_replication cours 100
172.26.0.3
172.26.0.2

Transactions et cohérence

1⃣ Vérifier le niveau de cohérance par défaut

docker exec -it cass1 cqlsh

puis

CONSISTENCY
Current consistency level is ONE.
💡 Le niveau de cohérence est ONE.

Niveaux de cohérence Cassandra
  • ONE (TWO, THREE): Le coordinateur reçoit la réponse du premier réplica (ou de deux, ou de trois) et la renvoie au client. Cette stratégie assure une haute disponibilité, mais au risque de renvoyer un document qui n’est pas synchronisé avec les autres réplicas. Dans ce cas, la cohérence des données n’est pas assurée
  • QUORUM : Le coordinateur reçoit la réponse de au moins réplicas. C’est la stratégie qui représente le meilleur compromis
  • ALL : Le coordinateur reçoit la réponse de tous les réplicas. Si un réplica ne répond pas, alors la requête sera en échec. C’est la stratégie qui assure la meilleure cohérence des données, mais au prix de la disponibilité du système

2⃣ Arrêter les noeuds

docker pause cass2 cass3
docker exec cass1 nodetool ring

3⃣ Mettre le niveau de cohérence à ALL et interroger les données

docker exec -it cass1 cqlsh

puis

use test_replication;
consistency all;
select * from cours where id = 1;
select * from cours where id = 10;
select * from cours where id = 100;
Comme attendu, la réponse renvoyée au client est une erreur pour toutes les requêtes.

4⃣ Tester de nouveau le iveau ONE

docker exec -it cass1 cqlsh

puis

use test_replication;
consistency one;
select * from cours where id = 1;
select * from cours where id = 10;
select * from cours where id = 100;
💡 Vu que le noeud cass1 contient les cours 10 et 100 (voir sharding), seule la première requête génère une erreur.