Apache HBase : colocation de RegionServers

Apache HBase : colocation de RegionServers

Vous appréciez notre travail......nous recrutons !

Ne ratez pas nos articles sur l'open source, le big data et les systèmes distribués, fréquence faible d’un email tous les deux mois.

Les RegionServers sont les processus gérant le stockage et la récupération des données dans Apache HBase, la base de données non-relationnelle orientée colonne de Apache Hadoop. C’est à travers leurs démons que s’effectue toute requête de type CRUD (pour Create, Read, Update et Delete). Conjointement au Master, ils sont les garants de la sauvegarde des données et de l’optimisation des performances. Dans les environnements de production, un unique RegionServer est déployé sur chaque nœud de calcul, permettant la mise à l’échelle aussi bien des charges de travail que du partage de stockage par l’ajout de noeuds additionnels.

De nos jours, de nombreuses entreprises font encore le choix d’une infrastructure on-premise, c’est-à-dire située dans les datacenters de l’entreprise, au contraire des infrastructures cloud. Leurs déploiements sur serveurs bare metal bénéficient de la totalité de l’espace mémoire de chaque machine. Parmi elles, celles dont les workloads reposent en majorité sur Apache HBase n’exploitent pas toujours la totalité de leurs ressources. En effet, la quantité de RAM qu’un RegionServer peut consommer est plafonnée par la JVM Java. Si chacun d’entre eux pouvait tirer parti de la totalité de la RAM qu’il a à disposition, leurs performances seraient potentiellement grandement accrues. Dans ce cas, la suppression de nœuds du cluster pourrait être envisagée, réduisant ainsi les coûts de license, dont le montant en dépend directement et une meilleur utilisation des ressources disponibles. De ce fait, sur une infrastructure on-premise, peut-on permettre à chaque RegionServer d’exploiter plus de ressources mémoires, afin de supporter la charge de travail due au retrait d’un ou plusieurs Workers ?

Colocation de RegionServers

Sur Apache Ambari, la taille de l’espace mémoire alloué à la JVM de chaque RegionServer est au choix : de 3 à 64 GB. Pourtant, la documentation conseille de ne pas dépasser les 30 GB. En effet, au-délà de ce seuil, le Garbage Collector, ayant pour mission de nettoyer les données qui ne sont plus utilisées en RAM, est surchargé : cela se concrétise par des pauses en plein milieu d’un workload, le rendant indisponible pendant une durée de plusieurs secondes. Une solution possible serait alors de multiplier le nombre de RegionServers par machine, afin de conserver des JVMs de 30 GB, tout en tirant parti de la RAM disponible.

Un projet sur Github décrit la marche à suivre pour lancer plusieurs RegionServers sur un même hôte, dans le cadre d’une distribution HDP gérée par Ambari. Il s’agit d’un script composé principalement d’une boucle for lançant les étapes classiques de démarrage d’un RegionServer, autant de fois qu’on le souhaite. Pour chaque nouvelle instance, le fichier de configuration initial sera copié et les numéros de ports seront incrémentés. Les dossiers de log et de PID de chaque RegionServer seront créés automatiquement.

Ce script doit être placé dans le répertoire de configuration de HBase, sur chacun des Workers sur lesquels on souhaite multiplier les RegionServers, pour ensuite être lancé par Ambari. Voici les quelques étapes manuelles nécessaires à la mise en place de ce script.

#!/bin/bash

# Change le nom du fichier `hbase-daemon.sh` en `hbase-daemon-per-instance.sh`
mv /usr/hdp/current/hbase-regionserver/bin/hbase-daemon.sh /usr/hdp/current/hbase-regionserver/bin/hbase-daemon-per-instance.sh

# Copie depuis ce projet le fichier `hbase-daemon.sh`
cp ./hbase-daemon.sh /usr/hdp/current/hbase-regionserver/bin/hbase-daemon.sh

# Donne les droits de lecture, d'écriture et d'exécution à l'administrateur sur le fichier copié
chmod +rwx /usr/hdp/current/hbase-regionserver/bin/hbase-daemon.sh

Bien que ces nouvelles instances ne soient pas visibles dans Ambari, elles le sont néanmoins sur la HBase Master UI. Après avoir effectué chacune de ces étapes, il suffit de démarrer classiquement chacun des RegionServer via l’interface d’Ambari. En effet, lorsqu’une action sera effectuée sur un RegionServer via l’interface d’Ambari, elle sera aussi lancée sur chaque RegionServer du même hôte. Par exemple, si un restart du RegionServers de l’hôte worker01 est effectué via Ambari, l’ensemble des nouvelles instances de RegionServer de l’hôte worker01 lanceront elles aussi un restart.

HBase Master UI

Environnement de test et méthodologie

Pour mesurer l’impact de ces nouvelles instances de RegionServers sur les performances, l’utilisation d’une batterie de tests YCSB est cohérente. YCSB (pour Yahoo! Cloud Serving Benchmark) est une suite de programmes open source servant à évaluer les capacités de récupération et de maintenance des programmes informatiques. Elle est souvent utilisée pour comparer les performances relatives des systèmes de gestion de bases de données NoSQL, tel que HBase. Cette batterie de tests reproduit les étapes suivantes identiques à chaque itération :

  • Création (ou re-création) d’une table de 50 régions
  • Insertions avec de nouvelles entrées (~150 GB)
  • YCSB workload A, « Update heavy » : ce workload est composé à 50/50 de lectures et d’écritures. Les mises à jour se font sans lecture préalable de l’élément. Un exemple d’application serait les cookies d’une session sur un site web.
  • YCSB workload F, « Read-modify-write » : pour ce workload, chaque élément sera lu, modifié puis réécrit. Un exemple d’application serait une base de données où les enregistrements d’un utilisateur sont lus et modifiés par l’utilisateur.

Pour chaque workload, le temps d’exécution (en secondes) et le débit d’opérations (en opérations/seconde) seront récupérés. Ces tests ont été effectués sur un cluster HDP 2.6.5, sur 4 Workers en bare-metal de 180 GB de RAM et 4 disques de 3 TB chacun, disposant d’une bande passante inter-machine de 10 GB/s. L’ensemble des RegionServers de ces 4 Workers formaient un « Region Server Group », ils étaient par conséquent exclusivement sollicités pour la batterie de tests, et pour aucun autre workload. Dans chaque situation, la batterie de test à été lancée au minimum trois fois.

Ajout de nouvelles instances

Cette première étape consiste en la suppression d’un nœud du cluster, puis en l’ajout de RegionServers sur différents hôtes afin de mesurer l’évolution des performances. Le tableau suivant présente les résultats : « w1 » signifie « Worker 1 » et les batonnets représentent le nombre de RegionServers sur chaque hôte. Enfin l’indication “w̶1̶” indique que le noeud “Worker 1” a été retiré du cluster HBase pour le test en question. Les résultats exposés sont des moyennes calculées sur l’ensemble des batteries de tests.

Tableau récapitulatif des performances obtenues après suppression d'un hôte

On remarque que l’ajout d’un ou plusieurs RegionServers sur chaque hôte ne compense pas la perte d’une machine. De plus, un déséquilibre de RegionServers d’un hôte à un autre fait dégringoler les performances. En effet, le Master voit chaque RegionServers indépendamment, comme s’ils avaient chacun leur propre machine. Ainsi, les régions (parcelles de données) sont réparties équitablement sur chaque RegionServers. Un hôte se retrouvant avec plus de RegionServers qu’un autre devra traiter plus de régions : la charge de travail se retrouve alors moins bien répartie entre les machines. Puisqu’un RegionServer ne compense par la perte d’une machine, cela prouve l’existence d’un goulot d’étranglement à une certaine étape du parcours des données.

Optimisation de la configuration

Cette étude consiste en la modification de propriétés sur Ambari afin d’obtenir de meilleures performances de nos nouveaux RegionServers. Les propriétés en question sont les suivantes :

  • DataNodes :
    • Nombre maximum de threads (dfs.datanode.max.transfer.threads)
    • RAM allouée aux DataNodes (dtnode_heapsize)
  • RegionServers :
    • Nombre de handlers (hbase.regionserver.handler.count)
    • RAM allouée aux RegionServers (hbase_regionserver_heapsize)

Le tableau suivant indique les performances obtenues initialement, ensuite avec 2 RegionServers par Worker, puis avec la configuration la plus effective.

Tableau récapitulatif des performances obtenues avec optimisation

Comme on peut le voir, les gains à l’ajout d’un RegionServer sur chaque Worker sont à hauteur de 10% : ils sont par conséquent négligeables, et expliquent les résultats de la première étude, amplifié par la prise en compte d’une marge d’erreur réaliste de 3%. Les gains avec 3 RegionServers par Worker ou plus sont identiques au cas précédent, aucun bénéfice n’est donc engendré.

Parmi les propriétés testées, seulement deux d’entre elles ont permis d’obtenir la configuration la plus efficace pour augmenter les gains avec 2 RegionServers par Worker. En ajoutant 10GB de RAM aux RegionServers (hbase_regionserver_heapsize=30.720) et 4000 threads pour le transfert de données des DataNodes (dfs.datanode.max.transfer.threads=20.480), on obtient 11% de gain pour le workload A, et 21% pour le F, qui sont les deux workloads incluant des lectures. Encore une fois, les gains avec 3 RegionServers après optimisations n’impliquent aucun changement. Bien qu’un gain de 21% ne puisse être qualifié d’important, il n’en est pas moins intéressant.

Pour finir, de nouvelles propriétés ont été testées mais n’ont pas su apporter de bénéfice concret :

  • io.file.buffer.size : taille du buffer des I/O à travers le DataNode.
  • dfs.datanode.handler.count : nombre de handlers disponibles par DataNode pour répondre aux requêtes.
  • dfs.datanode.balance.bandwidthPerSec : niveau maximal de bande passante que chaque DataNode peut utiliser.
  • dfs.datanode.readahead.bytes : nombre d’octet à lire en avance par rapport à l’élément lu.
  • dfs.client.read.shortcircuit.streams.cache.size : taille du cache du client lors d’une lecture en shortcircuit.

Analyse des métriques

L’analyse de divers métriques d’activité a permis de dégager des hypothèses expliquant les gains obtenus. Les métriques en question, récupérées sur chaque machine, sont : l’évolution de la charge CPU (user, system), celle de la RAM (used, free, swap), celle des I/O (nombre de transferts, débit d’écriture/lecture, débit de requêtes) et la répartition des charges (run queue, load average, nombres de tâches en attente de disque).

Hypothèses :

  • L’augmentation du nombre de threads des Datanodes augmente les requêtes de lecture/écriture sur les disques, engendrant des tâches en attente d’IO disponibles. Le nombre de threads par défaut était donc insuffisant à l’ajout d’un RegionServer pour atteindre le seuil de performances des DataNodes.
  • A l’ajout de RAM au niveau des RegionServers, on peut supposer que les lectures se font au niveau du BlockCache, réduisant ainsi le nombre de requêtes de lecture allant jusqu’au disque, ce qui réduit les tâches en attente de disque. Cela expliquerait les bénéfices des workloads de lecture, négligeables pour celui d’écriture, avec ou sans optimisation.

Par conséquent, nous pouvons affirmer que le goulot d’étranglement se trouve bel bien au niveau des disques. En effet, les performances en insertion augmentent légèrement grâce à la pression que place un deuxième RegionServer sur les disques mais ne vont pas plus loin justement car elles ne dépendent que des disques. Aussi, les performances en lecture sont meilleures grâce à la pression des threads, mais surtout grâce à l’agrandissement des différents caches de lecture. De plus, il est intéressant de noter que le nombre de requêtes ne double pas non plus totalement à l’ajout d’un second RegionServer. Sans goulot, les performances n’auraient donc pas doublé.

Ajout de disques

Jusqu’ici, les machines fonctionnaient avec 4 disques de 3 TB, mais comment évolueraient les performances si elles en avaient plus ? 8 disques ont par conséquent été ajoutés à chaque machine. Les résultats des tests sont présentés dans le tableau suivant :

Tableau récapitulatif des performances obtenues avec 12 disques

Tout d’abord, on remarque une différence de performance de 22% sur le workload A par rapport au cas initial, alors qu’ils sont plus ou moins identiques pour les deux autres types de test. En revanche, sur le même workload, les gains passent à 1% avec 2 RegionServers par hôte, puis 10% avec optimisation. L’augmentation du nombre de disques à donc eu un impact significatif sur les performances de notre RegionServer, mais l’ajout d’une instance supplémentaire, même avec une optimisation, ne présente finalement que peu d’intérêt.

Conclusion

Comme nous avons pu le constater, les performances d’écriture et de lecture, dans notre environnement, sont loin d’être doublées à l’ajout d’un second RegionServer sur chaque Worker. Le DataNode fait alors office de goulot d’étranglement logiciel et permet au mieux d’obtenir un gain de 21%. Les RegionServers sont optimisés pour drainer un maximum de performances à eux seuls, et fonctionnent en trio avec les Node Managers de Yarn et les DataNodes d’HDFS. Cet environnement a été conçu pour n’avoir qu’un seul RegionServer par Worker, comme nous le montre le gain de performance avec un seul RegionServer à l’ajout de disques.

En revanche, ce cas de figure peut bénéficier à un cluster en surplus de régions. En effet, les régions sont équitablement partagées entre chaque RegionServer, sans occasionner de perte de performances. Aussi, pour certains cas d’usage comme le workload F, la suppression d’un noeud physique peut être envisagée afin d’économiser les coûts de license et d’exploitation de celui-ci sans engager de baisse de performance significative.

Partagez cet article

Canada - Maroc - France

Nous sommes une équipe passionnée par l'Open Source, le Big Data et les technologies associées telles que le Cloud, le Data Engineering, la Data Science le DevOps…

Nous fournissons à nos clients un savoir faire reconnu sur la manière d'utiliser les technologies pour convertir leurs cas d'usage en projets exploités en production, sur la façon de réduire les coûts et d'accélérer les livraisons de nouvelles fonctionnalités.

Si vous appréciez la qualité de nos publications, nous vous invitons à nous contacter en vue de coopérer ensemble.

Support Ukrain