Il y a 8 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 :
[sql]INSERT into locks (lock_name) values (‘mon_lock’) IF NOT EXISTS;[/sql]
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 :
[sql]cqlsh:test> INSERT INTO lock (lockname) values (‘mon_lock’) IF NOT EXISTS;
[applied]
———–
True[/sql]
Dans le cas où une autre machine a pris le lock on obtient le résultat suivant :
[sql]cqlsh:test> INSERT INTO lock (lockname) values (‘mon_lock’) IF NOT EXISTS;
[applied] | lockname
———–+———-
False | mon_lock[/sql]
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 :
[sql]CREATE TABLE lock (
lockname text PRIMARY KEY
) with default_time_to_live = 180[/sql]
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 !
Commentaire