Découvrez les décisions de conception derrière la nouvelle prise en charge de HBase pour les MOB.
Apache HBase est une base de données de valeurs clés distribuée, évolutive, performante et cohérente qui peut stocker une variété de types de données binaires. Il excelle dans le stockage de nombreuses valeurs relativement petites (< 10 Ko) et offre des lectures et des écritures à faible latence.
Cependant, il existe une demande croissante de stockage de documents, d'images et d'autres objets modérés (MOB) dans HBase tout en maintenant une faible latence pour les lectures et les écritures. Un tel cas d'utilisation est une banque qui stocke les documents clients signés et numérisés. Autre exemple, les agences de transport peuvent souhaiter stocker des instantanés de la circulation et des voitures en mouvement. Ces MOB sont généralement à écriture unique.
Malheureusement, les performances peuvent se dégrader dans les situations où de nombreuses valeurs de taille modérée (100 Ko à 10 Mo) sont stockées en raison de la pression d'E/S sans cesse croissante créée par les compactages. Prenons le cas où 1 To de photos provenant de caméras de circulation, chacune d'une taille de 1 Mo, sont stockées quotidiennement dans HBase. Des parties des fichiers stockés sont compactées plusieurs fois via des compactages mineurs et, éventuellement, les données sont réécrites par des compactages majeurs. Parallèlement à l'accumulation de ces MOB, les E/S créées par les compactages ralentiront les compactages, bloqueront davantage le vidage du magasin de mémoire et bloqueront éventuellement les mises à jour. Un grand magasin MOB déclenchera des fractionnements régionaux fréquents, réduisant la disponibilité des régions concernées.
Afin de remédier à ces inconvénients, les ingénieurs de Cloudera et d'Intel ont implémenté le support MOB dans une branche HBase (hbase-11339 :HBase MOB). Cette branche sera fusionnée avec le maître dans HBase 1.1 ou 1.2, et est également déjà présente et prise en charge dans CDH 5.4.x.
Les opérations sur les MOB sont généralement intensives en écriture, avec des mises à jour ou des suppressions rares et des lectures relativement peu fréquentes. Les MOB sont généralement stockés avec leurs métadonnées. Les métadonnées relatives aux MOB peuvent inclure, par exemple, le numéro de voiture, la vitesse et la couleur. Les métadonnées sont très petites par rapport aux MOB. Les métadonnées sont généralement accessibles à des fins d'analyse, tandis que les MOB ne sont généralement consultés de manière aléatoire que lorsqu'ils sont explicitement demandés avec des clés de ligne.
Les utilisateurs veulent lire et écrire les MOB dans HBase avec une faible latence dans les mêmes API, et veulent une cohérence, une sécurité, un instantané et une réplication HBase solides entre les clusters, etc. Pour atteindre ces objectifs, les MOB ont été déplacés du chemin d'E/S principal de HBase vers un nouveau chemin d'E/S.
Dans cet article, vous découvrirez cette approche de conception et pourquoi elle a été sélectionnée.
Approches possibles
Il y avait quelques approches possibles à ce problème. La première approche que nous avons envisagée consistait à stocker les MOB dans HBase avec des politiques de fractionnement et de compactage ajustées - un MaxFileSize souhaité plus grand diminue la fréquence de fractionnement de la région, et moins ou pas de compactages peuvent éviter la pénalité d'amplification d'écriture. Cette approche améliorerait considérablement la latence et le débit d'écriture. Cependant, avec le nombre croissant de fichiers stockés, il y aurait trop de lecteurs ouverts dans un seul magasin, encore plus que ce qui est autorisé par le système d'exploitation. En conséquence, beaucoup de mémoire serait consommée et les performances de lecture se dégraderaient.
Une autre approche consistait à utiliser un modèle HBase + HDFS pour stocker les métadonnées et les MOB séparément. Dans ce modèle, un seul fichier est lié par une entrée dans HBase. Il s'agit d'une solution client, et la transaction est contrôlée par le client - aucune mémoire côté HBase n'est consommée par les MOB. Cette approche fonctionnerait pour des objets de plus de 50 Mo, mais pour les MOB, de nombreux petits fichiers entraînent une utilisation inefficace de HDFS, car la taille de bloc par défaut dans HDFS est de 128 Mo.
Par exemple, disons qu'un NameNode a 48 Go de mémoire et que chaque fichier fait 100 Ko avec trois répliques. Chaque fichier prend plus de 300 octets en mémoire, donc un NameNode avec 48 Go de mémoire peut contenir environ 160 millions de fichiers, ce qui nous limiterait à ne stocker que 16 To de fichiers MOB au total.
Comme amélioration, nous aurions pu assembler les petits fichiers MOB en plus gros, c'est-à-dire qu'un fichier pourrait avoir plusieurs entrées MOB, et stocker le décalage et la longueur dans la table HBase pour une lecture rapide. Cependant, il est difficile de maintenir la cohérence des données et de gérer les MOB supprimés et les petits fichiers MOB dans les compactages.
De plus, si nous devions utiliser cette approche, nous devrions envisager de nouvelles politiques de sécurité, perdre les propriétés d'atomicité des écritures et potentiellement perdre la sauvegarde et la reprise après sinistre fournies par la réplication et les instantanés.
Conception MOB HBase
En fin de compte, étant donné que la plupart des préoccupations concernant le stockage des MOB dans HBase impliquent les E/S créées par les compactages, la clé était de déplacer les MOB hors de la gestion par régions normales pour éviter les divisions et les compactages de région là-bas.
La conception HBase MOB est similaire à l'approche HBase + HDFS car nous stockons les métadonnées et les MOB séparément. Cependant, la différence réside dans une conception côté serveur :memstore met en cache les MOB avant qu'ils ne soient vidés sur le disque, les MOB sont écrits dans un HFile appelé "fichier MOB" à chaque vidage, et chaque fichier MOB a plusieurs entrées au lieu d'un seul fichier dans HDFS pour chaque MOB. Ce fichier MOB est stocké dans une région spéciale. Toutes les lectures et écritures peuvent être utilisées par les API HBase actuelles.
Écrire et lire
Chaque MOB a un seuil :si la longueur de la valeur d'une cellule est supérieure à ce seuil, cette cellule est considérée comme une cellule MOB.
Lorsque les cellules MOB sont mises à jour dans les régions, elles sont écrites dans le WAL et le memstore, tout comme les cellules normales. Lors du vidage, les MOB sont vidés dans les fichiers MOB, et les métadonnées et les chemins des fichiers MOB sont vidés pour stocker les fichiers. Les fonctionnalités de cohérence des données et de réplication HBase sont natives de cette conception.
Les modifications MOB sont plus importantes que d'habitude. Dans la synchronisation, les E/S correspondantes sont également plus importantes, ce qui peut ralentir les opérations de synchronisation de WAL. S'il existe d'autres régions qui partagent le même WAL, la latence d'écriture de ces régions peut être affectée. Cependant, si la cohérence et la non-volatilité des données sont nécessaires, WAL est indispensable.
Les cellules sont autorisées à se déplacer entre les fichiers stockés et les fichiers MOB dans les compactages en modifiant le seuil. Le seuil par défaut est de 100 Ko.
Comme illustré ci-dessous, les cellules qui contiennent les chemins des fichiers MOB sont appelées cellules de référence . Les balises sont conservées dans les cellules, nous pouvons donc continuer à nous fier au mécanisme de sécurité HBase.
Les cellules de référence ont des balises de référence qui les différencie des cellules normales. Une balise de référence implique une cellule MOB dans un fichier MOB, et donc une résolution supplémentaire est nécessaire lors de la lecture.
En lecture, le scanner du magasin ouvre des scanners au memstore et stocke les fichiers. Si une cellule de référence est rencontrée, l'analyseur lit le chemin du fichier à partir de la valeur de la cellule et recherche la même clé de ligne dans ce fichier. Le cache de bloc peut être activé pour les fichiers MOB en cours d'analyse, ce qui peut accélérer la recherche.
Il n'est pas nécessaire d'ouvrir des lecteurs à tous les fichiers MOB; un seul est nécessaire en cas de besoin. Cette lecture aléatoire n'est pas impactée par le nombre de fichiers MOB. Ainsi, nous n'avons pas besoin de compacter les fichiers MOB encore et encore lorsqu'ils sont suffisamment volumineux.
Le nom du fichier MOB est lisible et comprend trois parties :le MD5 de la clé de démarrage, la dernière date des cellules de ce fichier MOB et un UUID. La première partie est la clé de démarrage de la région à partir de laquelle ce fichier MOB est vidé. Habituellement, les MOB ont un TTL défini par l'utilisateur, vous pouvez donc trouver et supprimer les fichiers MOB expirés en comparant la deuxième partie avec le TTL.
Instantané
Pour être plus conviviaux avec l'instantané, les fichiers MOB sont stockés dans une région factice spéciale, dans laquelle l'instantané, l'exportation/clone de table et l'archive fonctionnent comme prévu.
Lors du stockage d'un instantané dans une table, on crée la région MOB dans l'instantané et ajoute les fichiers MOB existants dans le manifeste. Lors de la restauration de l'instantané, créez des liens de fichiers dans la région MOB.
Nettoyage et compactages
Il existe deux situations dans lesquelles les fichiers MOB doivent être supprimés :lorsque le fichier MOB a expiré et lorsque le fichier MOB est trop petit et doit être fusionné avec des fichiers plus volumineux pour améliorer l'efficacité de HDFS.
HBase MOB a une corvée dans le maître :il analyse les fichiers MOB, trouve ceux qui ont expiré déterminés par la date dans le nom de fichier et les supprime. Ainsi, l'espace disque est récupéré périodiquement en vieillissant les fichiers MOB expirés.
Les fichiers MOB peuvent être relativement petits par rapport à un bloc HDFS si vous écrivez des lignes où seules quelques entrées sont qualifiées de MOB ; aussi, il pourrait y avoir des cellules supprimées. Vous devez supprimer les cellules supprimées et fusionner les petits fichiers en plus gros pour améliorer l'utilisation de HDFS. Les compactages MOB ne compactent que les petits fichiers et les gros fichiers ne sont pas touchés, ce qui évite le compactage répété en gros fichiers.
Quelques autres choses à garder à l'esprit :
- Savoir quelles cellules sont supprimées. Dans chaque compactage majeur HBase, les marqueurs de suppression sont écrits dans un fichier del avant d'être supprimés.
- Dans la première étape des compactages MOB, ces fichiers del sont fusionnés en de plus grands.
- Tous les petits fichiers MOB sont sélectionnés. Si le nombre de petits fichiers est égal au nombre de fichiers MOB existants, ce compactage est considéré comme majeur et s'appelle un compactage ALL_FILES.
- Ces fichiers sélectionnés sont partitionnés par la clé de démarrage et la date dans le nom de fichier. Les petits fichiers de chaque partition sont compactés avec des fichiers del afin que les cellules supprimées puissent être supprimées ; pendant ce temps, un nouveau HFile avec de nouvelles cellules de référence est généré, le compacteur valide le nouveau fichier MOB, puis il charge en masse ce HFile dans HBase.
- Une fois les compactages dans toutes les partitions terminés, si un compactage ALL_FILES est impliqué, les fichiers del sont archivés.
Le cycle de vie des fichiers MOB est illustré ci-dessous. Fondamentalement, ils sont créés lorsque memstore est vidé et supprimés par HFileCleaner du système de fichiers lorsqu'ils ne sont pas référencés par l'instantané ou ont expiré dans l'archive.
Conclusion
En résumé, la nouvelle conception HBase MOB déplace les MOB hors du chemin d'E/S principal de HBase tout en conservant la plupart des fonctionnalités de sécurité, de compactage et d'instantané. Il répond aux caractéristiques des opérations dans MOB, rend l'amplification d'écriture des MOB plus prévisible et maintient de faibles latences en lecture et en écriture.
Jincheng Du est ingénieur logiciel chez Intel et contributeur HBase.
Jon Hsieh est ingénieur logiciel chez Cloudera et membre HBase committer/PMC. Il est également le fondateur d'Apache Flume et un committer sur Apache Sqoop.