Publié par

Il y a 5 ans -

Temps de lecture 2 minutes

Leader election avec Cassandra

Ces dernières années les architectures horizontales sont devenues la norme. On se retrouve alors bien souvent avec des fermes contenant 5, 10 ou bien plus de serveurs identiques chacun pouvant traiter le même type de requêtes.

Que faire si l’on souhaite que l’un de ces serveurs ait un rôle particulier à un instant T ? Il faut alors choisir un leader parmi notre ferme de serveurs. La solution la plus simple est de mettre en dur le nom de la machine leader dans notre code. Mais cette solution est trop simple et introduit un SPOF dans notre infrastructure dans le cas où notre machine maitre est indisponible.

Il nous faut donc un mécanisme permettant d’élire dynamiquement un leader parmi une ferme de serveurs.

Dans cet article nous utiliserons Cassandra, une base noSQL distribuée sans SPOF.

L’élection d’un leader revient à l’acquisition d’un lock par un serveur de notre ferme. La machine ayant acquis le lock est alors élue leader.

Pour mettre en place un lock distribué, nous allons nous appuyer sur une fonctionnalité apparue avec Cassandra 2.0, les « Lightweight transactions« . Celles-ci permettent d’écrire une requête du type :

INSERT into locks (lock_name) values ('mon_lock') IF NOT EXISTS;

Ce mécanisme permet d’assurer la création de notre lock de manière unique au sein de notre cluster Cassandra. Cette fonctionnalité se base sur le protocole de consensus Paxos permettant à un système distribué de s’accorder sur une proposition sans avoir besoin d’un serveur Master. Pour plus d’information sur ce protocole se référer au document: « Paxos made simple ».

Si la ligne a pu être créée on obtient alors le résultat suivant :

cqlsh:test> INSERT INTO lock (lockname) values ('mon_lock') IF NOT EXISTS;

 [applied]
-----------
      True

Dans le cas où une autre machine a pris le lock on obtient le résultat suivant :

cqlsh:test> INSERT INTO lock (lockname) values ('mon_lock') IF NOT EXISTS;

 [applied] | lockname
-----------+----------
 False | mon_lock

Et le schéma de notre table dans Cassandra, avec un TTL (« time to live ») par défaut permettant de s’assurer qu’une machine ne conservera pas le lock ad vitam aeternam :

CREATE TABLE lock (
  lockname text PRIMARY KEY
) with default_time_to_live = 180

Pour encore plus de facilité il est facile d’exposer ce service via une interface REST simple :

  • Un PUT sur l’URL /v1/locks/mon_lock renverra un status 201 (« Created ») dans le cas où le serveur cible a pu créer le lock
  • Il renverra un 409 (« Conflict ») dans le cas où le lock est pris par un autre serveur.

Et voilà une façon simple de gérer un lock distribué sur une infrastructure, plus besoin d’utiliser Zookeeper, etcd ou Redis dans ce but !

Publié par

Publié par Matthieu Nantern

Matthieu est un consultant Java senior spécialisé en DevOps, Apache Cassandra et la performance des applications. Depuis plus de 8 ans il remplit des missions agiles de développement, d'architecture et de conseils pour diverses sociétés. Récemment il est devenu formateur sur Apache Cassandra. Il travaille actuellement sur un projet de développement d'une plateforme IoT pour un grand groupe français.

Commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Xebian, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.