Retour sur le 4e Meetup Elasticsearch

Mercredi 4 décembre, le quatrième Meetup Elasticsearch s’est réuni chez OpenDataSoft, une startup spécialisée dans le développement d’une plateforme SAAS de gestion de données structurées, de leur valorisation et représentation. Ils sont installés à Paris dans la pépinière 27 avec un grand nombre d’autres startups dans des locaux originaux dont l’architecture crée une atmosphère décalée et créative. On est loin des couloirs uniformes d’une banque d’affaires.

Accueil

La soirée commence avec le désormais traditionnel accueil de David Pilato avec l’annonce de la sortie de la version 1.0.0.Beta2 dans la semaine. Elle apporte deux fonctionnalités très attendues : une API de sauvegarde et restauration et l’API d’agrégation présentée lors du meetup précédent et qui doit dépasser les  limitations des facettes actuelles.

David nous annonce aussi que la version 1.0.0 finale sortira au premier trimestre 2014, vraisemblablement autour de la fin février.

Analyse orientée business de vos logs

Ensuite, Vincent Spiewak monte sur la scène pour présenter une solution de collecte et d’analyse des logs orientés business. La solution s’appuie sur trois outils complémentaires :

  • Logstash pour la collecte et la structuration des logs,
  • Elasticsearch pour le stockage et la recherche
  • Kibana pour l’analyse des logs.

Notons que si Kibana est conçu pour fonctionner avec Elasticsearch (il a d’ailleurs été racheté par la société éponyme), Logstash est indépendant et pourrait être remplacé par un autre outil de collecte.

Logstash est un outil de collecte et de structuration des logs. Il dispose d’un grand nombre de types d’entrées (fichier, queue, bases de données diverses, TCP, UDP …) qui lui permettent de lire les logs en provenance d’un très grand nombre de source.

Il dispose ensuite d’un grand nombre de filtres qui lui permettent de structurer et de transformer les logs. De façon générale, un log est une ligne de texte accompagné d’un timestamp dont on souhaite extraire le maximum d’informations.
Le premier filtre mis en œuvre est généralement un filtre grok auquel on fournit le pattern d’une ligne de code. Le filtre transformera la ligne de log en un objet JSON qui est transmis à la suite de la chaine. Il y a quelques réglages à faire pour que le timestamp inclus dans la ligne de log soit pris en compte; autrement Logstash utilisera la date du traitement.

D’autres filtres pourront ajouter ou supprimer des champs, transformer ou normaliser un champ. Le filtre Geoip permet de localiser une adresse IP et d’ajouter les informations correspondantes issues d’une base Maxmind. Il est alors possible de savoir de quel pays et de quelle ville se connectent vos utilisateurs.

Une fois le log retravaillé, logstash l’envoi vers une des cinquante sorties possibles. Ici, nous nous intéressons à la sortie vers un index elasticsearch.

Elasticsearch va servir de base de données. Il stockera les logs et sera consulté par Kibana. La seule chose à prévoir à ce niveau, est de définir le mapping avant la première indexation afin de garantir la qualité de la recherche et du rendu des facettes.

Enfin, Kibana est un outil permettant de construire à la volée des tableaux de bord dynamiques dans une interface web. Selon votre inspiration et les données dont vous disposerez, vous pouvez construire des tableaux à destination des ops, pour suivre l’état de l’infrastructure, d’autres pour les  développeurs qui seront intéressés par les erreurs accompagnées de leur pile ou d’autres pour le marketing avec les informations fonctionnelles extraites des URL ou autres logs dédiés.

Les graphiques se mettent à jour en temps réel lorsque la base est alimentée en continu par Logstash.
Il est aussi possible de naviguer dans les données, tous les graphiques s’adaptant en conséquence.

La vue des tableaux étant plus parlante qu’un long discours, je vous invite à voir le site de Kibana qui offre une belle démo.

Le GBIF France et son portail

Marie-Elise Lecoq est venue nous présenter le portail français du GBIF (Global Biodiversity Information Facility). Il s’agit d’un portail international d’informations sur la biodiversité. Autrement dit, c’est une énorme source de données fournissant 12000 bases de données contenant plus de 400 millions d’occurrences de plus d’un million d’espèces.

Marie-Elise travaille pour le point nodal français qui est géré par cinq personnes, dont deux informaticiens. Ils gèrent eux-mêmes 17 millions de données qui sont centrées sur la France.

Le portail français est une application AngularJS propulsée par Play2 et qui repose sur Elasticsearch pour la recherche et MongoDB pour le stockage (plus une touche de PostgreSQL.)

Marie-Elise nous explique que le choix d’un modèle documentaire est venu naturellement. Leurs bases ne se composent que d’une collection qui contient des données très hétérogènes. Les données sont anciennes, elles remontent parfois du 17e siècle. Et peuvent provenir de formats divers comme des fiches papier, des feuilles Excel ou d’autres bases de données. L’ensemble des données possibles est décrit par le standard Darwin Core qui contient 172 champs dont seulement 5 sont obligatoires.

Face à des documents creux, utiliser une base de données relationnelle serait peu efficace alors que les bases documentaires sont particulièrement adaptées. Ils ont donc choisi de conserver les données dans MongoDB pour profiter de son mécanisme de sauvegarde et de les indexer dans Elasticsearch pour pouvoir effectuer des recherches.

Avec, la sortie de la version 1.0.0 d’Elasticsearch et son API de sauvegarde, ils pensent pouvoir se passer de MongoDB et simplifier leur système.

La recherche dans la base s’effectue via quatre onglets qui regroupent les critères de chaque axe de recherche :

  • taxonomique ;
  • géographique (possibilité de dessiner la zone de recherche sur la carte) ;
  • historique (dans une plage de dates) ;
  • par jeux de données.

Les résultats sont présentés sur une carte qui utilise Leafleat. Les données géographiques sont encore gérées par une base PostgreSQL mais seront prochainement intégrées dans Elasticsearch qui deviendra l’unique base de données du système.

OpenDataSoft

Après la pause pizzas et bières règlementaire, Clément Tourriere est venu nous présenter comment OpenDataSoft utilise Elasticsearch.

OpenDataSoft offre une API en mode SAAS qui permet de charger puis de jouer sur un jeu de données important.
L’application, écrite en Python, conserve les données dans MongoDB et les indexe dans Elasticsearch. Une petite base MySQL s’occupe des données de gestion (utilisateurs…) Un front AngularJS utilise l’API et offre une visualisation simple des données à destination des développeurs.

Clément indique que les principaux apports d’Elasticsearch sont:

  • la recherche en temps réel (utile pour les données de transport);
  • la navigation dans les données via les facettes ;
  • les capacités d’analyse, toujours via les facettes ;
  • la gestion des données géographiques.

il est possible la voir en œuvre sur des données ouvertes à l’adresse http://public.opendatasoft.com

Un premier écran sobre, assez classique, permet de rechercher un jeu de données. On retrouve un champ de recherche à la Google. À gauche, les facettes permettent de naviguer dans les données selon des axes préétablis. Sous le champ de recherche se trouve la liste paginée des résultats.

Une fois un jeu de données choisi, l’écran de présentation des données offre plusieurs onglets contenant les informations sur le jeu, les données sous forme tabulaire ou cartographique, un outil d’analyse graphique, un outil d’export et la présentation de la requête à faire dans l’API et de son résultat. Des filtres permettent de naviguer dans la collection de données.

L’onglet d’analyse présente les données sous la forme d’un graphe qui est construit par l’utilisation d’une terms_stats. OpenDataSoft a dû modifier la facette pour qu’elle réponde entièrement à leur besoin dans le cas des agrégations croisées. La customisation est simple à mettre en œuvre, mais doit être refaite presque à chaque nouvelle version d’Elasticsearch.

L’arrivée de l’API d’agrégation qui permet de croiser les champs devrait leur permettre d’abandonner leurs modifications pour utiliser les composants natifs d’ES.

La recherche géographique est un autre élément important de l’API. La branche principale gère tous les types GeoJSON. La version stable les gère presque tous. Le « presque tous » pose quelques problèmes bientôt résolus. Clément insiste cependant sur les performances de la recherche. Trouver des points dans un polygone très efficace, du moins au niveau d’Elasticsearch. Sauf qu’au-delà d’un millier de points dans le résultat, leur API commence à charger trop de données et rencontre des problèmes de charge tant du côté du serveur que du client.

La solution est de faire du clustering des résultats au niveau du serveur. Les points proches sont regroupés pour former un groupe qui affiche le nombre de points inclus à l’intérieur. Lorsqu’on zoome sur la carte, les groupes encore présents sont découpés en groupes plus petits jusqu’à présenter les données unitaires. En plus de faciliter la montée en charge, cette approche améliore l’expérience utilisateur. Il est possible d’avoir une vue d’ensemble sur un pays ou une région puis de zoomer où l’on souhaite avoir des détails.

Dessine-moi un index

Arrive ensuite Adrien Grand pour nous parler du fonctionnement interne d’un index Lucene. Adrien est « software developer » chez Elasticsearch, mais surtout commiter sur Lucene.

La présentation d’Adrien est disponible en ligne.

Le principe de l’indexation, c’est de modifier la représentation des données pour les adapter aux recherches qui seront faites dessus. Les opérations d’indexation sont souvent considérées comme lentes, car elles nécessitent de réaliser des traitements importants sur les données. Malgré cette réputation, l’indexation sur de bons outils comme Lucene reste performante. Le site http://people.apache.org/~mikemccand/lucenebench, qui effectue des tests de performance sur Lucene en indexant Wikipedia mesure des débits de 220 Go/h sur des documents texte de 4 ko.

Si les bases de données classiques utilisent des B-Tree, Lucene fonctionne très différemment. L’index est découpé en segments, chacun contenant une liste de termes classée dans l’ordre alphabétique. Chaque terme est identifié par sa position et dispose de la liste des identifiants des documents qui contiennent le terme. À côté, les documents sont classés dans une liste et identifiés par leur position.

Term dictionnary
term ordinaltermposting list
0data0, 1
1index0, 1
2lucene 0
3term0
4sql1
Document list
doc iddocument
0Lucene in action
1Relational Databases
Cette structure a l’avantage d’être très rapide. Les nouveaux documents sont ajoutés à la fin, dans une écriture séquentielle très rapide. De plus, les données ne sont pas modifiables ce qui permet les lectures concurrentes sans utiliser le moindre verrou. Les termes sont identifiés par un ordinal qui peut être utilisé pour le tri et les facettes (facilite l’usage de table de hachage). De plus, les intersections sont très rapides, quelle que soit la taille des champs.

Par contre, la modification d’un document seul est plus couteuse, les anciennes valeurs sont marquées supprimées, les nouvelles ajoutées et les segments fusionnés. C’est pour cela qu’Elasticsearch regroupe les mises à jour de l’index et ne les applique que périodiquement.

Adrien nous présente ensuite le cycle de vie d’une requête comme la TermQuery. C’est l’occasion de montrer que les structures de stockages ont été adaptées pour compresser raisonnablement les contenus tout en conservant de bonnes performances pour les recherches. Ainsi, les termes ne sont pas écrits en entier. Un transducteur à états finis conserve les préfixes et conduit vers une liste de termes dont seuls les derniers caractères sont précisés. L’arbre des préfixes est conservé en mémoire, alors que le dictionnaire complet est conservé sur disque et compressé en ne répétant pas les préfixes.

La posting list, ou liste des documents associés à un terme, est compressée de façon à gagner de la place tout en laissant la lecture très rapide. Pour cela, seule la différence avec la valeur précédente est conservée. Puis les nombres sont regroupés par blocs de taille fixe et sont codés sur le nombre de bits nécessaire pour le maximum du bloc. Les dernières valeurs sont stockées au format vInt.

Posting list1,3,4,6,8,20,22,26,30,31
delta1,2,1,2,2,12,2,4,4,1
groupes de 4(pour l’exemple)[1,2,1,2][2,12,2,4]4,1
codage de chaque nombre2 bits/val4bits/valvInt
Les valeurs de champs sont stockées sur disque, par blocs de 16 ko compressés avec LZ4.

Au final, une recherche effectue deux lectures aléatoires par champ recherché et une lecture aléatoire par document retourné. Les champs dont la fréquence est 1 sont optimisés et ne nécessitent qu’une lecture aléatoire au lieu de deux.

De plus, le dictionnaire des termes et les listes de posting, tiennent généralement dans le cache IO du système d’exploitation, diminuant les nombres de lectures effectives. D’où la règle communément admise de donner la moitié de la mémoire à la JVM d’Elasticsearch et l’autre moitié à l’OS.