6.1 Qui a inventé HBase et pourquoi

Dans cette conférence, nous parlerons d'un outil aussi merveilleux que Hbase, qui a récemment gagné en popularité : par exemple, Facebook l'utilise comme base de son système de messagerie, et cela en dit déjà long.

La conférence parlera du concept de Big Table et de sa mise en œuvre gratuite, des caractéristiques de travail et des différences par rapport aux bases de données relationnelles classiques (telles que MySQL et Oracle) et aux stockages clé-valeur tels que Redis, Aerospike et memcached. Comme d'habitude, commençons par l'historique du problème. Comme beaucoup d'autres projets BigData, Hbase est né d'un concept développé par Google. Les principes sous-jacents à Hbase ont été décrits dans l' article Bigtable : A Distributed Storage System for Structured Data .

Comme nous en avons discuté dans les conférences précédentes, les fichiers ordinaires sont assez bien adaptés au traitement de données par lots à l'aide du paradigme MapReduce. D'autre part, les informations stockées dans des fichiers sont plutôt difficiles à mettre à jour ; Les fichiers sont également privés de la possibilité d'accès aléatoire. Pour un travail rapide et pratique avec un accès aléatoire, il existe une classe de systèmes nosql tels que le stockage clé-valeur, tels que Aerospike, Redis, Couchbase, Memcached. Cependant, le traitement par lots est généralement très gênant dans ces systèmes. Hbase est une tentative de combiner la commodité du traitement par lots avec la commodité de la mise à jour et de l'accès aléatoire.

6.2 Modèle de données

HBase est une base de données clé-valeur distribuée, orientée colonne et multiversion.

  • Les données sont organisées en tables indexées par une clé primaire appelée RowKey dans Hbase.
  • Pour chaque clé RowKey, un ensemble illimité d'attributs (ou colonnes) peut être stocké.
  • Les colonnes sont organisées en groupes de colonnes appelées Column Family. En règle générale, les colonnes qui ont le même modèle d'utilisation et de stockage sont combinées dans une famille de colonnes.
  • Pour chaque attribut, plusieurs versions différentes peuvent être stockées. Différentes versions ont un horodatage différent.

Les enregistrements sont stockés physiquement dans l'ordre de tri RowKey. Dans ce cas, les données correspondant aux différentes familles de colonnes sont stockées séparément, ce qui permet, si nécessaire, de ne lire que les données de la famille de colonnes souhaitée.

Lorsqu'un certain attribut est supprimé, il n'est pas physiquement supprimé immédiatement, mais est uniquement marqué d'un indicateur de désactivation spécial. La suppression physique des données se produira plus tard, lorsque l'opération de compactage majeur sera effectuée.

Les attributs appartenant au même groupe de colonnes et correspondant à la même clé sont stockés physiquement sous forme de liste triée. Tout attribut peut être absent ou présent pour chaque clé, et si l'attribut est absent, cela n'entraîne pas la surcharge de stockage des valeurs vides.

Les noms de liste et de groupe de colonnes sont fixes et ont une disposition claire. Au niveau du groupe de colonnes, des paramètres tels que la durée de vie (TTL) et le nombre maximal de versions stockées sont définis. Si la différence entre l'horodatage d'une version particulière et l'heure actuelle est supérieure à TTL, l'entrée est marquée pour suppression. Si le nombre de versions d'un certain attribut dépasse le nombre maximal de versions, l'enregistrement est également marqué pour suppression.

Le modèle de données Hbase peut être mémorisé comme une correspondance clé-valeur :

<table, RowKey, Column Family, Column, timestamp> -> Value

6.3 Opérations prises en charge

La liste des opérations prises en charge dans hbase est assez simple. 4 opérations principales sont supportées :

  • Put : ajoute une nouvelle entrée à hbase. L'horodatage de cette entrée peut être défini manuellement, sinon il sera automatiquement défini sur l'heure actuelle.
  • Get : Obtenir des données pour une RowKey spécifique. Vous pouvez spécifier la famille de colonnes à partir de laquelle nous prendrons les données et le nombre de versions que nous voulons lire.
  • Scan : lit les enregistrements un par un. Vous pouvez spécifier l'enregistrement à partir duquel nous commençons la lecture, l'enregistrement vers lequel lire, le nombre d'enregistrements à lire, la famille de colonnes à partir de laquelle la lecture sera effectuée et le nombre maximum de versions pour chaque enregistrement.
  • Supprimer : Marquez une version spécifique pour suppression. Il n'y aura pas de suppression physique, elle sera reportée au prochain Grand Compactage (voir ci-dessous).

6.4 Architecture

HBase est une base de données distribuée qui peut fonctionner sur des dizaines ou des centaines de serveurs physiques, garantissant un fonctionnement ininterrompu même si certains d'entre eux échouent. Par conséquent, l'architecture de HBase est assez complexe par rapport aux bases de données relationnelles classiques.

HBase utilise deux processus principaux pour son travail :

1. Region Server - Dessert une ou plusieurs régions. Une région est une plage d'enregistrements correspondant à une plage spécifique de RowKeys consécutives. Chaque région contient :

  • Le stockage persistant est le principal stockage de données dans HBase. Les données sont stockées physiquement sur HDFS, dans un format HFile spécial. Les données dans HFile sont stockées dans l'ordre de tri RowKey. Un couple (région, famille de colonnes) correspond à au moins un HFile.
  • MemStore - tampon d'écriture. Étant donné que les données sont stockées dans HFile d dans un ordre trié, il est assez coûteux de mettre à jour le HFile par enregistrement. Au lieu de cela, lors de l'écriture, les données entrent dans une zone de mémoire MemStore spéciale, où elles s'accumulent pendant un certain temps. Lorsque le MemStore est rempli à une valeur critique, les données sont écrites dans un nouveau HFile.
  • BlockCache - cache pour la lecture. Permet de gagner beaucoup de temps sur les données lues fréquemment.
  • Journal d'écriture anticipée (WAL) . Étant donné que les données sont écrites dans le magasin de mémoire, il existe un risque de perte de données en raison d'un plantage. Afin d'éviter que cela ne se produise, toutes les opérations avant la mise en œuvre effective des manipulations tombent dans un fichier journal spécial. Cela vous permet de récupérer des données après toute panne.

2. Serveur maître - le serveur principal du cluster HBase. Le maître gère la répartition des régions entre les serveurs de région, tient à jour un registre des régions, gère le lancement des tâches régulières et effectue d'autres travaux utiles.

Pour coordonner les actions entre les services, HBase utilise Apache ZooKeeper, un service spécial conçu pour gérer les configurations et synchroniser les services.

Lorsque la quantité de données dans la région augmente et atteint une certaine taille, Hbase commence à diviser, une opération qui divise la région par 2. Pour éviter des divisions constantes de régions, vous pouvez prédéfinir les limites des régions et augmenter leur maximum taille.

Étant donné que les données d'une région peuvent être stockées dans plusieurs HFiles, Hbase les fusionne périodiquement pour accélérer le travail. Cette opération est appelée compactage dans Hbase. Les compactages sont de deux types :

  • Compactage mineur . Démarre automatiquement, s'exécute en arrière-plan. A une faible priorité par rapport aux autres opérations Hbase.
  • Compactage important . Il est lancé à la main ou lors de l'apparition de certains déclencheurs (par exemple, par une minuterie). Il a une priorité élevée et peut ralentir considérablement le cluster. Les compactages majeurs sont mieux effectués à un moment où la charge sur le cluster est faible. Le compactage majeur supprime également physiquement les données précédemment marquées avec une pierre tombale.

6.5 Façons de travailler avec HBase

Shell HBase

Le moyen le plus simple de démarrer avec Hbase consiste à utiliser l'utilitaire shell hbase. Il est disponible immédiatement après l'installation de hbase sur n'importe quel nœud de cluster hbase.

Le shell Hbase est une console jruby avec prise en charge intégrée de toutes les opérations de base de Hbase. Voici un exemple de création d'une table d'utilisateurs avec deux familles de colonnes, de manipulations et de suppression de la table à la fin dans le shell hbase :

create 'users', {NAME => 'user_profile', VERSIONS => 5}, {NAME => 'user_posts', VERSIONS => 1231231231} 
put 'users', 'id1', 'user_profile:name', 'alexander' 
put 'users', 'id1', 'user_profile:second_name', 'alexander' 
get 'users', 'id1' 
put 'users', 'id1', 'user_profile:second_name', 'kuznetsov' 
get 'users', 'id1' 
get 'users', 'id1', {COLUMN => 'user_profile:second_name', VERSIONS => 5} 
put 'users', 'id2', 'user_profile:name', 'vasiliy' 
put 'users', 'id2', 'user_profile:second_name', 'ivanov' 
scan 'users', {COLUMN => 'user_profile:second_name', VERSIONS => 5} 
delete 'users', 'id1', 'user_profile:second_name' 
get 'users', 'id1' 
disable 'users' 
drop 'users'

API native

Comme la plupart des autres projets liés à hadoop, hbase est implémenté en Java, de sorte que l'API native est disponible en Java. L'API native est assez bien documentée sur le site officiel. Voici un exemple d'utilisation de l'API Hbase tiré de là :

import java.io.IOException;

import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

public class MyLittleHBaseClient {
  public static void main(String[] args) throws IOException {
	Configuration config = HBaseConfiguration.create();
	Connection connection = ConnectionFactory.createConnection(config);
	try {
  	Table table = connection.getTable(TableName.valueOf("myLittleHBaseTable"));
  	try {
    	Put p = new Put(Bytes.toBytes("myLittleRow"));
    	p.add(Bytes.toBytes("myLittleFamily"), Bytes.toBytes("someQualifier"),
    	Bytes.toBytes("Some Value"));
    	table.put(p);

    	Get g = new Get(Bytes.toBytes("myLittleRow"));
    	Result r = table.get(g);
    	byte [] value = r.getValue(Bytes.toBytes("myLittleFamily"),
      	Bytes.toBytes("someQualifier"));

    	String valueStr = Bytes.toString(value);
    	System.out.println("GET: " + valueStr);

    	Scan s = new Scan();
    	s.addColumn(Bytes.toBytes("myLittleFamily"), Bytes.toBytes("someQualifier"));
    	ResultScanner scanner = table.getScanner(s);
    	try {
       	for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
         	System.out.println("Found row: " + rr);
       	}
     	} finally {
       	scanner.close();
     	}
   	} finally {
     	if (table != null) table.close();
   	}
 	} finally {
   	connection.close();
 	}
  }
}

Thrift, REST et prise en charge d'autres langages de programmation

Pour travailler à partir d'autres langages de programmation, Hbase fournit l'API Thrift et l'API Rest. Sur cette base, des clients sont construits pour tous les principaux langages de programmation : python, PHP, Java Script, etc.

6.6 Certaines fonctionnalités de travail avec HBase

  1. Hbase s'intègre directement à MapReduce et peut être utilisé comme entrée et sortie à l'aide des tables spéciales TableInputFormat et TableOutputFormat.

  2. Il est très important de choisir la bonne RowKey. RowKey doit fournir une bonne répartition uniforme entre les régions, sinon il existe un risque de soi-disant "régions chaudes" - des régions qui sont utilisées beaucoup plus souvent que d'autres, ce qui conduit à une utilisation inefficace des ressources système.

  3. Si les données ne sont pas téléchargées individuellement, mais immédiatement par lots volumineux, Hbase prend en charge un mécanisme BulkLoad spécial qui vous permet de télécharger des données beaucoup plus rapidement qu'en utilisant des puts uniques. BulkLoad est essentiellement une opération en deux étapes :

    • Formation de HFile sans la participation de puts à l'aide d'un travail MapReduce spécial
    • Insertion de ces fichiers directement dans Hbase
  4. Hbase prend en charge la sortie de ses métriques sur le serveur de surveillance Ganglia. Cela peut être très utile lors de l'administration de Hbase pour aller au fond des problèmes de hbase.

clé de ligne

La RowKey est l'ID utilisateur, qui est un GUUID, une chaîne spécialement générée pour être unique au monde. Les GUUID sont répartis uniformément, ce qui permet une bonne répartition des données sur les serveurs.

Famille de colonnes

Notre stockage utilise deux familles de colonnes :

  • données. Ce groupe de colonnes stocke des données qui ne sont plus pertinentes à des fins publicitaires, telles que le fait qu'un utilisateur a visité certaines URL. Le TTL pour cette famille de colonnes est fixé à 2 mois, la limite du nombre de versions est de 2000.
  • données longues. Ce groupe de colonnes stocke des données qui ne perdent pas leur pertinence au fil du temps, telles que le sexe, la date de naissance et d'autres caractéristiques "éternelles" de l'utilisateur.

haut-parleurs

Chaque type de faits utilisateur est stocké dans une colonne distincte. Par exemple, la colonne Data:_v stocke les URL visitées par l'utilisateur et la colonne LongData:gender stocke le sexe de l'utilisateur.

L'horodatage de ce fait est stocké sous forme d'horodatage. Par exemple, dans la colonne Data:_v, l'horodatage correspond à l'heure à laquelle l'utilisateur a visité une URL spécifique.

Cette structure de stockage des données utilisateur correspond très bien à notre modèle d'utilisation et vous permet de mettre à jour rapidement les données utilisateur, d'obtenir rapidement toutes les informations nécessaires sur les utilisateurs et, à l'aide de MapReduce, de traiter rapidement les données de tous les utilisateurs à la fois.

6.7 Alternatives

HBase est assez complexe à administrer et à utiliser, donc avant d'utiliser HBase, il est logique d'examiner les alternatives :

  • Bases de données relationnelles . Une très bonne alternative, notamment dans le cas où les données tiennent sur une seule machine. Aussi, dans un premier temps, il faut penser aux bases de données relationnelles dans le cas où les transactions d'index autres que le primaire sont importantes.

  • Stockage clé-valeur . Les stockages comme Redis et Aerospike sont mieux adaptés lorsque la latence est nécessaire et que le traitement par lots est moins important.

  • Fichiers et leur traitement avec MapReduce . Si les données sont seulement ajoutées et rarement mises à jour/modifiées, il est préférable de ne pas utiliser HBase, mais simplement de stocker les données dans des fichiers. Pour simplifier le travail avec les fichiers, vous pouvez utiliser des outils tels que Hive, Pig et Impala.

L'utilisation de HBase est justifiée lorsque :

  • Il y a beaucoup de données, et elles ne tiennent pas sur un seul ordinateur/serveur
  • Les données sont fréquemment mises à jour et supprimées
  • Il existe une « clé » explicite dans les données, à laquelle il convient de lier tout le reste
  • Besoin d'un traitement par lots
  • Besoin d'un accès aléatoire aux données par des clés spécifiques