Le plugin Akka Persistence Titan ou comment changer de mentalité et remplacer les bases de données SQL par les bases de données NOSQL

Adrian Florea

Akka [1] est une boite à outil et un environnement d’exécution open source fonctionnant sur une JVM permettant de construire des applications hautement concurrentes, distribuées et résistantes. Il permet un traitement transactionnel temps réel sur la base du modèle d’acteur [2].

Akka est un ensemble d’outils logiciels évolutif non seulement en termes de performance mais aussi en termes de taille d’applications pour lesquelles il est utilisé. Le cœur d’Akka, l’acteur-Akka, est de très petite taille et peut facilement être utilisé au sein d’un projet existant qui nécessiterait une gestion concurrente asynchrone et non-verrouillée.  Akka fourni de très bonnes performances, qu’il soit exécuté seul ou de manière distribuée.

Les acteurs vous permettent également de gérer les défaillances à travers une supervision et un monitoring, gestion de charge (stratégies de backoff, timeouts et processing-isolation), de même que la scalabilité horizontale et verticale (ajouter plusieurs cœurs et/ou plusieurs machines). Il y a un nombre impressionnant de cas d’utilisation pour lesquels Akka convient parfaitement comme :

  • Le traitement transactionnel (jeux en ligne, finances/banques, trading, statistiques, les paris, médias sociaux, télécommunications)
  • Services de backend (tous secteurs, toutes application)
  • Service REST, SOAP, Cometd, WebSockets etc. qui se comporte comme un hub pour les messages / une couche d’intégration, scale up, scale out, tolérance aux pannes / HA
  • Concurrence / traitements parallèles (toutes apps)
  • Intégration de Camel en batch. Les acteurs divisent et conquièrent les charges de travail batch
  • Communications Hub (télécommunications, médias web, médias mobiles)
  • Traitement des flux d’évènements complexes

Étude de cas Pentalog

Chez Pentalog, nous utilisons déjà Akka et Titan depuis quelques années sur nos projets. Nous utilisons généralement une configuration basée sur Cassandra et Elasticsearch avec Akka qui fournit le squelette des systèmes back-end exposant REST, comme des APIs.

Pourquoi Titan ?

Les avantages des bases de données NOSQL

Les bases de données NOSQL ne sont absolument pas la future génération des bases de données SQL. Elles sont simplement une alternative et la question est plutôt de choisir le bon outil en fonction de ses besoins. La structure d’une base de données évolue régulièrement dans le temps à chaque fois que l’application évolue ou que de nouvelles fonctionnalités sont ajoutées. Ces modifications de structure sont plus difficiles à appréhender avec une base de données relationnelle.Si des colonnes sont ajoutées à une table existante, il faudra alors déterminer des valeurs par défaut pour les enregistrements existant où alors autoriser les valeurs nulles. Une autre stratégie serait d’utiliser des champs défini par l’utilisateur, mais cela impliquerait de nouvelles jointures et les jointures ralentissent les requêtes.

Dans le cas d’une base de données NOSQL, les modifications de structure sont gérées plus facilement. Toute nouvelle « colonne » d’une table n’existera pas tant qu’elle ne contiendra pas d’informations utiles. Il n’y a donc pas besoin de créer des scripts de migration DDL pour mettre à jour la base de données.

Généralement, les différents modules d’une application possèdent des attributs obligatoires et des règles de validations différentes pour conserver un comportement commun. Il existe différentes stratégies pour gérer cela dans une base de données relationnelle [5] mais il y aussi des inconvénients :

  • Dans les tables Single, il y aura des champs avec des valeurs nulles là où le type d’entité ne le nécessite pas.
  • Dans les tables Individual, récupérer des infos via des catégories va soit nécessiter des jointures et des contrôles d’existence dans les tables de détails, soit des réplications en ajoutant des colonnes discriminantes.

Sinon l’alternative est l’utilisation des bases de données NOSQL qui gèrent implicitement cela compte tenu de la flexibilité de leur schéma.

Dans quels cas doit-on utiliser une base de données orientée graphe ?

Le modèle de données associatif

Un graphe est un ensemble de nœuds (aussi appelés sommets ou « vertices ») connectés par des liens (aussi appelés arêtes ou « edges »). Tant les nœuds que les liens peuvent avoir des attributs, mais les liens peuvent également avoir de la direction (In, Out ou Both). L’enregistrement des graphes traite les nœuds et les liens de la même façon, ce qui le transforme en un candidat idéal chaque fois que les liens sont des citoyens de première classe dans un modèle de données [6]. De plus, il est bien connu que les bases de données orientées graphe s’ajustent de façon naturelle aux jeux de données de larges dimensions [7]. Intuitivement, beaucoup de modèles de la vie réelle – même un modèle de base de données relationnelle ou un diagramme ER – sont de type graphe. C’est parce que les graphes s’appliquent parfaitement aux domaines riches en modèles. L’émergence des applications sociales dans les dernières années a contribué massivement à la popularité des bases de données orientées graphe. Prenons l’exemple de Facebook, Twitter ou LinkedIn. Leur modèle de données est, en principe, un graphe d’utilisateurs connectés. On doit mentionner que ces bases de données orientées graphe ne sont pas une nouveauté. En fait, elles sont plus anciennes que les bases de données relationnelles si on parle, par exemple, du modèle de bases de données hiérarchiques [8].

Autorisation à fine granularité – cas d’utilisation classique d’une base de données orientée graphe

« Un concept d’autorisation doit exister pour s’assurer que les utilisateurs peuvent accéder uniquement aux données pour lesquelles ils ont des droits » – Implémenter l’autorisation à fin granularité avec des données relationnelles s’avère toujours être une tâche difficile parce qu’elle devrait être traitée comme un problème transversal, mais elle a également un caractère commercial. On devrait soit ajouter un groupe propriétaire / informations utilisateur aux données, soit ajouter des clés étrangères vers les données au niveau utilisateur / groupe. Supposons que « l’utilisateur » appartienne à un « groupe » qui peut accéder uniquement aux données des « clients » d’une « organisation » spécifique, on parle déjà d’une jointure à quatre tables. Dans le cas des bases de données orientées graphe, le scénario ci-dessus est d’habitude possible en reliant « l’utilisateur » au « rôle » et puis « le rôle » à « l’organisation » à travers les liens qui peuvent, par exemple, avoir comme propriété le niveau permission(s).

Pourquoi Titan en particulier

Titan est une base de données en graphe optimisée pour enregistrer et requêter des graphes contenant des centaines de milliards de nœuds et liens à travers un cluster multi-machines. Titan est une base de données transactionnelle qui peut supporter des milliers d’utilisateurs concurrents qui exécutent des transversales de graphes complexes en temps réel [9].
Parmi les bases de données orientées graphe, l’un des principaux avantages de Titan est la couche de persistance qui peut être pluguée. Cela signifie qu’en fonction des besoins spécifiques du projet, plusieurs bases de données peuvent être utilisées :

  • En mémoire – développée principalement pour les tests.
  • Apache Cassandra – hautement évolutive et conçue pour la gestion de grosses quantités de données structurées, appropriée si vous êtes intéressé par la tolérance Disponibilité et Partition
  • Apache HBase – orientée plutôt vers la tolérance Consistance et Partition du triangle CAP [10]
  • Oracle BerkleyDB – également sur le côté CP du triangle CAP, mais plus appropriée pour les opérations read-intensive.
  • Il y a aussi une implémentation de stockage AWS– respectivement AWS DynamoDB, qui peut être utilisée au lieu de déployer et gérer explicitement un moteur de stockage imposé au cas où votre projet doit être déployé sur AWS.

Tous les fournisseurs de persistance mentionnés ci-dessus peuvent être intégrés facilement avec Elasticsearch, Lucene ou SOLR pour l’interrogation des données full texte. Donc, pourquoi Titan ? Parce qu’il est intuitif, c’est une base de données orientée graphe, et extrêmement flexible en termes de stockage de données. Comme je l’ai déjà dit, c’est un excellent outil pour faire du bon boulot.

Les défis d’implémentation de ce plug-in

J’ai toujours été un utilisateur et un promoteur de l’open source et j’ai toujours tenté d’apporter mon aide à la communauté. Le développement akka-persistence-titan [11] est un exemple qui va dans ce sens. Au moment où j’ai commencé à travailler sur ce plugin, je connaissais déjà les concepts de persistance Titan et Akka supportés par Cassandra. J’avais quand même la sensation qu’il manquait quelque chose. Pour des raisons de performance, la persistance AKKA sérialise les journaux d’évènements et les instantanées (snapshots) en tant que tableaux de bits qui empêchent la lecture des données pour les applications tierce partie connectées directement à la couche de stockage. Je devais donc choisir entre la sérialisation des tableaux de bits et la performance d’un côté et JSON et les données lisibles par les humains de l’autre. Titan m’a permis d’avoir les deux.

L’implémentation initiale faisait partie du projet sur lequel je travaillais à ce moment-là. La première étape pour développer le plugin fut d’extraire l’implémentation depuis un autre projet et ajuster le code pour qu’il corresponde aux interfaces AKKA standard et passer les cas de test recommandés. Une fois prêts, j’ai utilisé Github pour héberger mon projet et j’ai essayé de trouver une manière de le mettre à disposition du public en tant que dépendance sbt/Maven.

Après quelques clics, il s’est avéré que l’OSSR [12] pouvait héberger des projets open source publics. Pour plus d’infos sur la manière d’héberger vos projets sur leurs référentiels, cliquez ici : http://central.sonatype.org/pages/ossrh-guide.html. Pour plus de détails sur l’utilisation des plugins, tapez sur Google « akka persistence titan » et vous serez redirigé vers la page Github.

Autre bonne nouvelle : AKKA encourage la communauté à développer des plugins et même de les promouvoir sur leur site web à l’adresse suivante : http://akka.io/community/. La communauté est responsable de cette page, qui est hébergée sur Github et qui peut être modifiée aussi facilement qu’en lançant une requête pull.

Quels conseils pour ceux qui souhaitent implémenter leur premier plugin Akka Titan ?

Bon… pour ceux qui utilisent des applications professionnelles « traditionnelles » et qui se basent exclusivement sur un seul type de base de données relationnelle pour la persistance, il est assez difficile de commencer à travailler avec des acteurs et une couche de stockage non relationnelle, spécialement avec une base de données orientée graphe. Cela requiert évidemment un certain changement de mentalité.

Avec Titan, la transition a été relativement simple car les graphes, en tant que modèles, sont plus proches de la réalité par rapport à une base de données normalisée, ou du moins pour moi cela fut plus simple à comprendre. Gremlin [13], le langage de requête par défaut de Titan, exige un peu plus de temps pour la prise en main, spécialement pour ceux ayant une expérience Groovy, mais je ne dirais pas qu’il soit plus complexe que SQL.

En ce qui concerne le modèle d’acteur implémenté en AKKA, mon premier conseil serait d’oublier tout ce que vous avez appris sur la concurrence dans une application classique multi-threads et recommencer à zéro. La puissance du modèle d’acteur vient précisément de sa simplicité. Les acteurs peuvent seulement modifier l’état privé et communiquer entre eux en échangeant des messages. Il n’y a pas d’état partagé entre plusieurs acteurs, donc ils sont intrinsèquement concurrents.

Une autre leçon apprise et suffisamment douloureuse est que, dans la plupart des cas, nous n’avons pas besoin de transactions ACID [14] dans nos applications. D’autres se sont rendus compte de ça avant moi et ont proposé des alternatives comme BASE [15]. Laissant de côté la mentalité ACID, admettre que l’éventuelle cohérence n’est pas suffisante dans la majorité des cas d’utilisation est le point de départ dans l’implémentation d’une application basée sur un modèle d’acteur, quelle que soit la couche de persistance. Compte tenu du fait que les données sont transférées à travers des messages asynchrones, vous devez trouver une façon de gérer tous les risques liés : le message arrive trop tard, il n’arrive pas du tout, il peut même arriver plusieurs fois que les acteurs peuvent ne répondre pas à temps ou simplement échouer.

Pour faire bref, au moment de concevoir un système distribué, n’oubliez pas « qu’il n’y a rien de gratuit » et faites attention au CAP [17] 🙂

 

[1] http://akka.io/
[2] https://en.wikipedia.org/wiki/Actor_model
[3] http://martinfowler.com/bliki/UserDefinedField.html
[4] https://www.infoq.com/news/2007/08/denormalization
[5] https://docs.oracle.com/cd/B14099_19/web.1012/b15901/mapping003.htm
[6] https://en.wikipedia.org/wiki/Graph_database
[7] http://systemg.research.ibm.com/database.html
[8] https://en.wikipedia.org/wiki/Hierarchical_database_model

[9] http://titan.thinkaurelius.com/
[10] https://en.wikipedia.org/wiki/CAP_theorem
[11] https://github.com/acflorea/akka-persistence-titan
[12] http://central.sonatype.org/
[13] http://gremlindocs.spmallette.documentup.com/
[14] https://en.wikipedia.org/wiki/ACID
[15] http://queue.acm.org/detail.cfm?id=1394128, https://neo4j.com/blog/acid-vs-base-consistency-models-explained/
[16] https://en.wikipedia.org/wiki/No_free_lunch_theorem
[17] https://en.wikipedia.org/wiki/CAP_theorem