Pages

Tuesday, October 4, 2011

Cassandra : Les problématiques à traiter lorsqu'on développe une application java

Cassandra fait parti de la famille des bases de données NoSQL. C'est une base de données dont on entend de plus en plus parler dès que l'on est confronté à devoir gérer de gros volumes de données, à être très performant et à vouloir monter en charge facilement.

De part sa conception, Cassandra a été nativement pensé pour être hautement distribué, hautement performant et avec une forte capacité de montée en charge. 

Cassandra est une très belle implémentation du modèle p2p. Tous les noeuds au sein d'un Cluster Cassandra ont le même rôle. Il n'y a pas de notion de maître/esclave...

Bref, Je ne vais pas vous énumérer les avantages à utiliser Cassandra car d'autres l'ont déjà très bien fait avant moi. Vous trouverez sur le wiki de Cassandra un ensemble de liens vers des présentation qui  décriront les concepts clés autour de Cassandra. Juste un dernier mot pour vous dire que Cassandra va bientôt sortir en v1.0.

Une fois votre choix arrêté : "ok, on part sur Cassandra", quelles sont les problématiques auxquels vous allez être confronté lors de sa mise en oeuvre? Je vais tenter d'apporter quelques réponses... C'est parti!

Design de votre modèle de données :
Une des premières choses à faire quand on commence à travailler avec Cassandra, c'est d'oublier tout ce qu'on vous a dit et ce que vous faisiez avec une base de données relationnelle : Le maître mot est dénormalisation.

Cassandra propose un modèle orienté "Column Family" inspiré par BigTable de Google. Je vous conseille dans un premier temps de bien comprendre le modèle de Cassandra (Keyspace, ColumnFamily, Column, SuperColum, Counter) avant de vous lancer. La documentation de DataStax sur le sujet ainsi que l'article sur le wiki sont un bon point départ.

Une fois le modèle de Cassandra compris, il faut axer la réflexion sur la façon dont vous allez requêter vos données. Le système de requêtage de Cassandra est limité (pas de jointures par exemple...). Il faut donc commencer par là pour être sûr de pouvoir faire ce que l'on veut faire.

Installer et paramétrer un cluster Cassandra
La force de Cassandra est de fonctionner avec un grand nombre de noeud dans un cluster. Le plus gros cluster dont j'ai entendu parler (dans cette interview de Jonathan Ellis) serait constitué de 400 noeuds... Juste énorme. Sans aller jusque là, il faut malgré tout rapidement vous familiariser avec le fonctionnement et l'administration d'un cluster Cassandra. Bref, il faut mettre les mains dedans. Je vous conseille cet articlecette video ou encore cette documentation DataStax décrivant la mise en oeuvre rapide d'un cluster cassandra. Cassandra fonctionne aussi en Single Node, cela peut toujours servir en terme de développement mais j'y reviendrai plus tard.

Il vous faut aussi comprendre le fichier de configuration principal de chaque noeud Cassandra : cassandra.yaml. Voici sa documentation.

Si vos serveurs acceptent le packaging Debian, Je vous conseille fortement d'utiliser celui proposé par Cassandra. Il vous permettra très rapidement de l'installer et surtout de le mettre à jour facilement!

Il faut aussi un peu de moyens... Pour pouvoir faire des tests sur votre cluster, il faut un environnement machines permettant de mettre en valeurs les capacités de Cassandra. Cela permet aussi pour vous rassurer avec des tests de performances valables avant d'arriver dans un environnement de production. La virtualisation de plusieurs noeuds sur un ("petit") serveur ne permettra pas de faire des tests de performances concluants.

Administrer et monitorer un cluster Cassandra
Cassandra fournit nativement un ensemble d'outils permettant d'administrer votre cluster :
  • cassandra-cli : c'est l'utilitaire en ligne de commande permettant de lire/ecrire dans votre cluster
  • nodetool : c'est l'utilisaire en ligne de commande permettant de monitorer et administrer les noeuds du cluster
En plus de ça, DataStax propose une application Web de monitoring et d'administration de votre cluster Cassandra : OpsCenter. C'est vraiment un superbe outil. Il y a une version gratuite pour le développement. J'ai cru comprendre (mais je me trompe peut être) qu'il y aura bientôt aussi une version production gratuite mais qui ne l'est pas pour le moment.


Gérer le "Eventuellement Consistant"
Cassandra propose un modèle "Eventuellement Consistant". Ces mots doivent normalement mettre la puce à l'oreille à n'importe quel développeur et faire un peu peur. 

Pour faire simple, selon le théorème CAP, il n'est pas possible d'avoir à la fois de la consistance (Consistency) , de la disponibilité (Availability) et une résistance au morcellement (Partition tolerance). Il n'est possible que d'en avoir 2 sur 3. Cassandra a choisi de mettre l'accent sur le "A" et le "P" et d'offrir la possibilité de choisir son niveau de consistance. Il est donc possible d'avoir un consistance forte avec Cassandra mais au détriment d'une dégradation du temps de latence (car il faut demander à plus de noeud dans le cluster de se mettre d'accord sur la valeur d'une donnée lors d'une lecture par exemple).

Il y est donc possible de choisir parmi plusieurs niveaux de consistances. Voici une documentation sur le site de DataStax sur le sujet pour vous guider dans votre choix.

Lock
Cassandra ne sait pas faire de Lock. C'est un inconvénient lié à son architecture. Il ne permet donc pas d’empêcher plusieurs clients de lire ou d'écrire un ensemble données portant sur les mêmes clés de votre modèle au même moment. Ce qui peut être fortement gênant, il ne faut pas le nier... Dans ce cas : "la réponse est ailleurs".

Il n'est pas impossible de faire du lock sur vos données mais en utilisant un système externe qui va gérer cela. Zookeeper va vous permettre de faire cela. C'est un système de synchronisation distribué de type sémaphore qui va vous permettre de faire des locks. Zookeeper n’entraîne pas de SPOF car il fonctionne aussi en cluster. Cage est une libraire Java qui s'appuie sur zookeeper et propose un système de lock basé sur des chemins. Voici un article qui vous explique en détail son utilité pour compléter l'utilisation de Cassandra. 

Transaction
Ok, vous faites du lock mais lock ne veut pas dire transaction... Cassandra assure une atomicité des données au niveau d'une même clé (même dans des columnFamily différentes). En revanche, comment faire si vous avez besoin d'une atomicité de données sur plusieurs clés car vos données sont fortement couplés et que vous ne pouvez pas faire autrement.

La réponse est "Just do it (yourself)". Une des approches est de mettre en oeuvre un système de transaction log dans une columnFamily dédiée. Le principe est donc : 
  • de logger la transation en sérialisant les données qui ont besoin d'être atomiques (json, xml, ...) et en insérant le résultats de la sérialisation en une fois dans une colonne d'une columFamily.
  • effectuer votre traitement en insérant vos données dans votre modèle.
  • de marquer ou supprimer la log de la transaction une fois le traitement terminé.
Ce système vous donne alors la possibilité de rejouer la log de la transaction si un souci est survenu pendant votre traitement. Ce système est abordé dans cette présentation (à partir du slide 24).


Comment dialoguer avec Cassandra
Cassandra expose toute son Api cliente via Thrift. L'utilisation native de thrift est déconseillée car c'est plutôt une Api de bas niveau s'adressant à des clients développeur plutôt qu'à des applications clientes.
Il faut donc choisir votre client pour vous adresser à Cassandra : Ils sont listés ici.

En java, il en existe plusieurs. Hector semble clairement le plus utilisé et le plus configurable. C'est celui que j'utilise.

Environnement de développement
Si vous utilisez maven, la plupart des librairies dont vous avez besoin sont mavenisées et disponibles dans les repository centraux (l'exception est Cage qui nécessite de déclarer un repository spécifique).

Vous aimez faire des tests unitaires et du TDD, pas de problèmes, c'est possible et ça se fait même très bien. Il est possible de lancer Cassandra et Zookeeper de façon "embedded" dans votre JVM.

Il est même possible si vous le souhaitez de lancer Cassandra de façon embarquée et d'y charger des données avant d’exécuter vos tests unitaires. Je vous propose d'aller jeter un oeil du côté de cassandra-unit si vous souhaitez faire ça.

Ecosystème en évolution permanente
Que ce soit sur les fonctionnalités de Cassandra, son outillage, son écosystème, il y a beaucoup de changements, d'évolutions et d'améliorations.

De grosses et nouvelles fonctionnalités apparaissent constamment. Par exemple, il y a quelque mois, entre la version 0.7.8 et la 0.8.0, un langage de requêtage le "CQL" est apparu et très prochainement Cassandra sort en version 1.0... Ça va très vite.


Il faut globalement rester en veille sur les blogs, twitter, les mailing list (Cassandra et Hector par exemple) pour voir ce qui se fait, ce qui sort. La communauté autour de Cassandra est grossissante et est très réactive.


Ne pas avoir peur de défaire
Comme les choses changent et évoluent, Il ne faut pas avoir peur de jeter un peu, de modifier souvent, de refactorer beaucoup votre code. C'est dû soit à une évolution de compréhension de Cassandra qui vous fait dire qu'il faut mieux faire autrement, soit à l'apparition d'une nouvelle fonctionnalité soit à un lecture sur un blog...

Il n'y a pas de secret, ma meilleure arme pour gérer ses changements sont : mes tests unitaires et mes tests d'intégrations et ça se passe bien!

Pour aller plus loin
Vous pouvez aller jeter un oeil dans le code source de Cassandra sous svn ici ou sur le miroir sous Git ici.
Vous pouvez aller lire la documentation sur le wiki sur l'architecture interne de Cassandra ici et voir cette vidéo.
Vous pouvez contribuer en commençant ici.

Pour Conclure
Utiliser Cassandra comme backend pour stocker vos données à un réel impact sur votre façon de développer votre application. C'est quelque part assez normal dans le sens si vous utilisez Cassandra, c'est que vous avez normalement beaucoup de données à gérer et qu'il faut de toute façon obligatoirement prendre ça en compte pour développer votre application...

Une fois les efforts produits, quel plaisir de rajouter un noeud dans le cluster pour monter en charge...
En fait, Cassandra, c'est très "DevOps" :-).