jeudi 22 janvier 2015

Introduction HBase Shell & HBase Java API

HBase : Architecture


Comme évoqué dans l’article HBase : Un Système de Base de Données Orientée Colonne, les tables HBase sont constituées d’un ensemble de familles de colonnes (regroupements logiques de colonnes) spécifiées lors de leur création. Chaque Column Family est composée d’un un nombre arbitraire de colonnes pouvant être ajoutées après la création de la table, à n’importe quel moment. Chaque ligne est identifiée par une clé. Une clé est un tableau d’octets ce qui fait que théoriquement toute donnée peut servir de clé. Les tables trient les entrées en fonction de leurs clés.
Pour répartir les données (dans le but d’équilibrer les charges) sur plusieurs nœuds d’un cluster, les lignes (identifiées par Row ID et ses Column Family) des tables sont partitionnées en plusieurs parties appelées des regions. Lors de la création d’une table, une seule region est créée, elle est ensuite automatiquement divisée en sous-parties lorsque sa taille atteint un seuil limite configurable. Chaque region est placée sur un nœud appelé region server



Master Server :

La tâche du serveur maître consiste à assigner les régions aux serveurs de régions enregistrés. Il maintient l’état du cluster et assure l’équilibre de charge entre les serveurs régions. Il réassigne automatiquement les régions d’un serveur de région défaillant et s’occupe de tous les changements du schéma de données. Pour accéder aux données, le client ne passe pas directement par le serveur maître mais plutôt par le serveur de région (Region Server).

Region Server

Les serveurs de région sont responsables des requêtes d’écriture et de lecture du client. Une communication est régulièrement établie entre le serveur maître et les serveurs de région. Cela permet aux serveurs de région de connaitre la liste des régions qu’ils gèrent et permet au serveur maître de savoir si un serveur de région est défaillant ou non. Lorsqu’une région d’un serveur de région nécessite d’être partitionnée (si la taille dépasse une limite fixée), ce dernier communique avec le maître pour lui signifier qu’une nouvelle région doit être créée. Si un serveur de région n’est plus joignable, il est automatiquement remplacé. Cette tâche est confiée à un autre service : ZooKeeper

ZooKeeper

Le service ZooKeeper est chargé de maintenir les informations du cluster en cas de défaillance. Le serveur maître et les serveurs de région sont tous enregistrés auprès du Zookeeper et si l’un d’eux subit une défaillance, Zookeeper se chargera de le faire réparer ou de le remplacer.

Modes d'exécution

HBase est framework avec une architecture distribuée. Cependant, son utilisation en mode non distribué est également possible. Il exite trois modes d'exécution : autonome (standalone), pseudo-distribué (pseudo-distributed) et distribué (fully distributed).

Le fonctionnement par défaut est configuré en mode autonome. Il suffit de télécharger le zip, le décompresser et mettre la variable d'environnement JAVA_HOME en place. Le fonctionnement en mode distribué nécessite l'installation d'Hadopp (pour l'utilisation du système de fichier HDFS) et la modification des fichiers de configuration (répertoire conf).

En mode « Standalone », HBase ne fait pas usage du système de fichiers HDFS. Il utilise plutôt le système de fichiers de la machine locale et tous les démons liés à Hbase sont installés en local (ZooKeeper, …) et s'exécutent sur la même JVM. Bien que ce mode soit très facile à installer, il est très peu performant du fait qu’il ne tire aucunement profit de la force du nombre que fournit HDFS. Ce mode est donc conseillé pour les développeurs qui en sont à leurs premiers pas avec HBase et qui désirent comprendre et jouer avec le système.

En mode pseudo-distribué, Hbase utilise le système de fichier Hadoop. Il est donc indispensable d'installer Hadoop. Comme en mode autonome, tous les démons sont installés sur la même machine et au sein de la même JVM. Le mode distribué nécessite au moins 2 machines afin de répartir les démons. Les deux modes pseudo-distribué et distribué nécessitent des configurations supplémentaires (hbase-site.xml).

Exemples Simples : HBase Shell & JAVA API

CREATE : création de table  :




static final String USERS_TABLE_NAME = "users";
    static final String USERS_COLUMN_FAMILY_INFO = "info";
    static final String USERS_COLUMN_FAMILY_PROFESSION = "profession";

    public static void main(String[] args) throws Exception {

        //configuration de la machine locale
        //Possibilité de renseigner pour une config distante :
        // conf.set("hbase.master", "192.168.15.20:60000");
        // conf.set("hbase.zookeeper.quorum", "192.168.15.20");
        //conf.set("hbase.zookeeper.property.clientPort","2181");
        // or  conf.addResource(new Path("/home/user/hbase/core-site.xml"));  conf.addResource(new Path("/home/user/hbase/hbase-site.xml"));
        Configuration conf = HBaseConfiguration.create();

        HBaseAdmin admin = new HBaseAdmin(conf);

        HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(USERS_TABLE_NAME));

        tableDescriptor.addFamily(new HColumnDescriptor(USERS_COLUMN_FAMILY_INFO));
        tableDescriptor.addFamily(new HColumnDescriptor(USERS_COLUMN_FAMILY_PROFESSION));

        admin.createTable(tableDescriptor);
        System.out.println("tableAvailable = " + admin.isTableAvailable(USERS_TABLE_NAME));

    }

ALTER : Pour modifier la structure des tables ....

Modifions le nombre de version associé à la colunm family profession




static final String USERS_TABLE_NAME = "users";
    static final String USERS_COLUMN_FAMILY_PROFESSION = "profession";

    public static void main(String[] args) throws Exception {

        //configuration de la machine locale
        //Possibilité de renseigner pour une config distante :
        // conf.set("hbase.master", "192.168.15.20:60000");
        // conf.set("hbase.zookeeper.quorum", "192.168.15.20");
        //conf.set("hbase.zookeeper.property.clientPort","2181");
        // or  conf.addResource(new Path("/home/user/hbase/core-site.xml"));  conf.addResource(new Path("/home/user/hbase/hbase-site.xml"));
        Configuration conf = HBaseConfiguration.create();

        HBaseAdmin admin = new HBaseAdmin(conf);

        HTableDescriptor hTableDescriptor = admin.getTableDescriptor(USERS_TABLE_NAME.getBytes());
        HColumnDescriptor[] families=hTableDescriptor.getColumnFamilies();
        for (  HColumnDescriptor h : families) {
            System.out.println("Column Family = " + h.getNameAsString());
            System.out.println("Max version = " + h.getMaxVersions());
        }

        admin.disableTable(USERS_TABLE_NAME);
        HColumnDescriptor professionCF = new HColumnDescriptor(USERS_COLUMN_FAMILY_PROFESSION);
        professionCF.setMaxVersions(5);
        admin.modifyColumn(USERS_TABLE_NAME, professionCF); // modifying existing ColumnFamily
        admin.enableTable(USERS_TABLE_NAME);
        admin.flush(USERS_TABLE_NAME);
        hTableDescriptor = admin.getTableDescriptor(USERS_TABLE_NAME.getBytes());
        families=hTableDescriptor.getColumnFamilies();
        for (  HColumnDescriptor h : families) {
            System.out.println("Column Family = " + h.getNameAsString());
            System.out.println("Max version = " + h.getMaxVersions());
        }

    }

PUT : L’opération PUT (insert dans le mode SQL) permet de sauvegarder/insérer les données dans  une table HBase créée préalablement avec l'opération CREATE.

Insertion d’une ligne identifiée par 001E : Ajout d’une nouvelle colonne (type) à la Column Family (profession) avec comme valeur Etudiant


On ajoute l’université du user 001E. Cette colonne appartient également à la Column Family profession :


Ajout d’un nouvel user avec comme identifiant 001S, type de profession Ingénieur, nom de Column Family info, prenom, age ...



Ajout successif de l’entreprise pour user 001S. Toutes les valeurs écrasées sont versionnées selon le nombre de version de la Column Family profession :



static final String USERS_TABLE_NAME = "users";
    static final String USERS_COLUMN_FAMILY_INFO = "info";
    static final String USERS_COLUMN_FAMILY_PROFESSION = "profession";
    static final String ROW_ETUDIANT_1 = "001E";
    static final String ROW_INGENIEUR_1 = "001S";
    static final String CQ_NAME = "nom";
    static final String CQ_PRENOM = "prenom";
    static final String CQ_TYPE = "type";
    static final String CQ_ENTREPRISE = "entreprise";
    static final String CQ_UNIVERSITE = "universite";
    static final String CQ_AGE = "age";

    public static void main(String[] args) throws Exception {

        //configuration de la machine locale
        //Possibilité de renseigner pour une config distante :
        // conf.set("hbase.master", "192.168.15.20:60000");
        // conf.set("hbase.zookeeper.quorum", "192.168.15.20");
        //conf.set("hbase.zookeeper.property.clientPort","2181");
        // or  conf.addResource(new Path("/home/user/hbase/core-site.xml"));  conf.addResource(new Path("/home/user/hbase/hbase-site.xml"));
        Configuration conf = HBaseConfiguration.create();

        HTable table = new HTable(conf, USERS_TABLE_NAME);

        Put putEtudiant = new Put(Bytes.toBytes(ROW_ETUDIANT_1));
        putEtudiant.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_TYPE), Bytes.toBytes("Etudiant"));
        table.put(putEtudiant);

        putEtudiant = new Put(Bytes.toBytes(ROW_ETUDIANT_1));
        putEtudiant.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_UNIVERSITE), Bytes.toBytes("ENI"));
        table.put(putEtudiant);

        Put putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_TYPE), Bytes.toBytes("Ingénieur"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), Bytes.toBytes("Larbo Technologie"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_INFO), Bytes.toBytes(CQ_NAME), Bytes.toBytes("Dupond"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_INFO), Bytes.toBytes(CQ_PRENOM), Bytes.toBytes("Jean"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_INFO), Bytes.toBytes(CQ_AGE), Bytes.toBytes("23"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), Bytes.toBytes("Entreprise 1"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), Bytes.toBytes("Entreprise 2"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), Bytes.toBytes("Entreprise 3"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), Bytes.toBytes("Entreprise 4"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), Bytes.toBytes("Entreprise 5"));
        table.put(putIngenieur);

        putIngenieur = new Put(Bytes.toBytes(ROW_INGENIEUR_1));
        putIngenieur.add(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), Bytes.toBytes("Entreprise 6"));
        table.put(putIngenieur);

        table.flushCommits();
        table.close();

    }

 GET : la lecture de données s’effectue grâce à l’opération GET (select). Elle permet de lire les valeurs d’une ligne d’une ou plusieurs familles de colonne.

Recherche des valeurs par identifiant :



On peut afficher les valeurs précédentes de la colonne Entreprise liée à la column family profession pour user 001S :





import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;

import java.util.List;

public class GetUser {

    static final String USERS_TABLE_NAME = "users";
    static final String USERS_COLUMN_FAMILY_PROFESSION = "profession";
    static final String ROW_INGENIEUR_1 = "001S";
    private static final String TABS = "\t\t\t\t";

    public static void main(String[] args) throws Exception {

        //configuration de la machine locale
        //Possibilité de renseigner pour une config distante :
        // conf.set("hbase.master", "192.168.15.20:60000");
        // conf.set("hbase.zookeeper.quorum", "192.168.15.20");
        //conf.set("hbase.zookeeper.property.clientPort","2181");
        // or  conf.addResource(new Path("/home/user/hbase/core-site.xml"));  conf.addResource(new Path("/home/user/hbase/hbase-site.xml"));
        Configuration conf = HBaseConfiguration.create();

        HTable table = new HTable(conf, USERS_TABLE_NAME);

        Get get = new Get(Bytes.toBytes(ROW_INGENIEUR_1));
        get.addFamily(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION));
        Result result = table.get(get);
        List<Cell> cells = result.listCells();
        for (Cell cell : cells) {
            System.out.printf("%s%scolumn=%s:%s, timestamp=%d, value=%s\n",
                    Bytes.toString(CellUtil.cloneRow(cell)),
                    TABS,
                    Bytes.toString(CellUtil.cloneFamily(cell)),
                    Bytes.toString(CellUtil.cloneQualifier(cell)),
                    cell.getTimestamp(),
                    Bytes.toString(CellUtil.cloneValue(cell)));
        }

        table.close();
    }
}

SCAN :  c'est l’opération la plus importante. Elle permet de faire de recherche, de filtrer les données par :
-          les valeurs de clé,
-          les noms de familles de colonnes,
-          les nomes de colonnes,
-          les valeurs  des colonnes
-          le numéro de version (timestamp) associés aux colonnes.


Le SCAN de base est équivalent à la requête SQL : select * from users


On peut effectuer une recherche de tous les users dont l’identifiant est préfixé par 002




 static final String  USERS_TABLE_NAME  = "users";
    static final String  SATART_WITH    = "\"002\"";
 private static final String TABS    = "\t\t\t\t";

 public static void main( String[] args ) throws Exception
 {

  // configuration de la machine locale
  // Possibilité de renseigner pour une config distante :
  // conf.set("hbase.master", "192.168.15.20:60000");
  // conf.set("hbase.zookeeper.quorum", "192.168.15.20");
  // conf.set("hbase.zookeeper.property.clientPort","2181");
  // or conf.addResource(new Path("/home/user/hbase/core-site.xml")); conf.addResource(new Path("/home/user/hbase/hbase-site.xml"));
  Configuration conf = HBaseConfiguration.create();

  HTable table = new HTable( conf, USERS_TABLE_NAME );

  byte[] prefix = SATART_WITH.getBytes();
  Scan scan = new Scan();
  // scan.setStartRow("002".getBytes());
  // scan.setStopRow("003".getBytes());
  PrefixFilter prefixFilter = new PrefixFilter( prefix );
  scan.setFilter( prefixFilter );

  ResultScanner resultScanner = table.getScanner( scan );
  Result result = resultScanner.next();
  while ( result != null )
  {

   List<Cell> cells = result.listCells();
   for ( Cell cell : cells )
   {
    System.out.printf( "%s%scolumn=%s:%s, timestamp=%d, value=%s\n", Bytes.toString( CellUtil.cloneRow( cell ) ), TABS,
      Bytes.toString( CellUtil.cloneFamily( cell ) ), Bytes.toString( CellUtil.cloneQualifier( cell ) ),
      cell.getTimestamp(), Bytes.toString( CellUtil.cloneValue( cell ) ) );
   }
   result = resultScanner.next();
  }

  table.close();
 }

DELETE : permet de supprimer le contenu d’un enregistrement, d’une famille de colonnes, d’une version d’une colonne ou des toutes les versions d’une colonne.

Suppression de toutes les valeurs des versions de la column family profession pour user 001S.


Suppression de la column family profession de la table users :




 static final String USERS_TABLE_NAME = "users";
    static final String USERS_COLUMN_FAMILY_PROFESSION = "profession";
    static final String ROW_INGENIEUR_1 = "001S";
    static final String CQ_ENTREPRISE = "entreprise";

    public static void main(String[] args) throws Exception {

        //configuration de la machine locale
        //Possibilité de renseigner pour une config distante :
        // conf.set("hbase.master", "192.168.15.20:60000");
        // conf.set("hbase.zookeeper.quorum", "192.168.15.20");
        //conf.set("hbase.zookeeper.property.clientPort","2181");
        // or  conf.addResource(new Path("/home/user/hbase/core-site.xml"));  conf.addResource(new Path("/home/user/hbase/hbase-site.xml"));
        Configuration conf = HBaseConfiguration.create();

        HTable table = new HTable(conf, USERS_TABLE_NAME);

        //création du composant pour la suppression d'une ligne spécifique : 001S
        Delete delete = new Delete(Bytes.toBytes(ROW_INGENIEUR_1));
        //On peut spécifier la version de la valeur associée à la colonne à supprimer
        delete.setTimestamp(1421608776178l);

        //On peut spécifier la version de la cellule à supprimer
        delete.deleteColumn(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), 1421608776178l);

        //suppression de toutes les versions suppérieures ou égales 1421608776178
        delete.deleteColumns(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), Bytes.toBytes(CQ_ENTREPRISE), 1421608776178l);

        //suppression de toutes les valeurs d'une column family avec toutes les versions
        delete.deleteFamily(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION));

        //suppression de toutes les valeurs d'une column family dont la version est supérieure ou égale 1421608776178
        delete.deleteFamily(Bytes.toBytes(USERS_COLUMN_FAMILY_PROFESSION), 1421608776178l);

        table.delete(delete);
        table.close();
    }

vendredi 16 janvier 2015

HBase : Un Système de Base de Données Orientée Colonne

                     Introduction

Vous avez sûrement entendu parler de BIG DATA ! Il s’agit d’un concept qui consiste à modéliser, stocker et traiter un ensemble de données hyper volumineuses, croissantes et hétérogènes (de trillions de données, des milliards de milliards de données). Qui parle donc de BIG DATA, parle certainement de données à stocker et à gérer…

On estime par ailleurs que 80% des données d’une entreprise sont non-structurées et inexploitées… et le volume augmente de plus en plus rapidement. De plus, les infrastructures modernes nous permettent de stocker de plus en plus de données à moindre coût. Le modèle des bases de données relationnelles a montré leur limite pour stocker ces données. Ce modèle bien que très puissant, pose le problème du passage à l’échelle.  Des sites comme Google ou Facebook, possèdent plusieurs centaines de millions d’entrées dans leurs bases de données et tout autant de visites journalières. Par conséquent, une seule machine ne peut pas gérer la base de données, de plus pour des raisons de fiabilité, ces bases de données sont dupliquées pour que le service ne soit pas interrompu en cas de panne. La méthode consiste donc à rajouter des serveurs pour dupliquer les données et ainsi augmenter les performances et résister aux pannes. Seulement, dû aux propriétés fondamentales (ACID) sur lesquelles une base de données relationnelle repose, cette approche connait des limites.


L’objectif de cet article n’est pas d’exposer les détails des limites des systèmes de gestion de base de données traditionnelle (relationnelle) mais de présenter un système de base de données permettant de gérer de données volumineuse qu’on appelle communément de NOSQL. Sachant qu’il en existe plusieurs types (document, graphe, orienté colonne, etc.), nous présentons le type orientée colonne avec comme exemple HBase

Base de données orientée colonne ou base de données orientée Map

Pour une base de donnée orientée colonne, la notion de colonne n'a pas réellement de sens.  Le modèle de gestion des données repose sur une notion de couple {clé, valeur}. Le nom de la colonne peut être vue comme la clé. Il y a en effet, aucune notion de colonne telle que l'on peut l'entendre dans une base de données relationnelle. Donc pour éviter toute ambigüité avec la notion de colonne pour les bases de données relationnelles, je préfère utiliser le terme de base de données orientée Map.
Les données d’une base de données orientée Map (colonne) sont identifiées par une clé unique (équivalent d’une clé primaire pour les bases de données relationnelle). Ainsi on associe à ces identifiants un ensemble de données composées d’un couple clé, valeur (d’où la notion de Map). Dans le monde relationnel, ces clés sont appelées colonne.


Bien  que les données soient organisées en tables, leur disposition est totalement différente. Ainsi alors que les colonnes d’une base de données relationnelle sont statiques et présentes pour chaque ligne, celles d’une base de données orientée colonnes (disons les clés) sont dynamiques et présentes uniquement pour les lignes concernées. En d’autres termes, il est possible d’ajouter des colonnes (clés) à une ligne à tout moment et le coût de stockage d’un null est 0.



Prenons un exemple d’une base de données relationnelle, une table est un ensemble de données organisées en colonnes dont le nombre est fixe quel que soit le nombre d’enregistrements. Lorsque l’on insère un enregistrement dans cette table, on spécifie une valeur pour chaque colonne, null étant une valeur par défaut. Voici un exemple de représentation d’une personne :



Les bases de données orientées colonnes sont pensées pour stocker des millions de colonnes, ce qui en fait des bases adaptées au stockage one-to-many. Elles sont bien adaptées par exemple pour le stockage de : messages,  posts , commentaires, etc.
Les requêtes pour accéder aux données sont généralement simples. Il est en effet possible de faire des requêtes par clé, ou ensemble de clés et d’y adjoindre un prédicat sur un intervalle de clés. Un exemple de requête typique : toutes les valeurs des clés (colonnes) de l’identifiant 15 ou toutes les valeurs des clés (colonnes) dont le nom est compris entre "aaa" et "abb" pour l’identifiant 178 ou la valeur de la clé "aaa" pour les identifiants 26 à 31.
HBase : un exemple de base de données orientée colonne

Hbase est un exemple de SGBD orienté colonne. Il a été calqué sur les travaux de BigTable de Google et se repose sur le système de fichier distribué (HDFS : hadoop distributed file system).  HDFS est caractérise par une haute tolérance aux pannes et permet un accès très rapide aux données. C'est un système de fichier adapté aux applications gérant de grands ensembles de données. HBase est particulièrement bien adaptée pour le stockage de très grandes collections et a des performances exceptionnelles pour des lectures et écritures massives de données. Elle a été conçue pour stocker de très grandes tables (des milliards d'enregistrement avec des millions de colonnes) de données.

Les données sont organisées dans des tables identifiées par une simple chaîne de caractère (le nom de la table). Une table est composée d'un ensemble de lignes appelée Row. Chaque Row (ligne) est identifiée par un identifiant unique appelé ROWKEY (Identifiant). Dans Hbase, une ROWKEY n'a pas de type spécifique (c'est un simple tableau d'octets).

Une ligne Hbase est d'une part identifiée par une ROWKEY et composée d'un ensemble de couple clé-valeur (colonne – valeur associée). Dans le jargon Hbase, la clé est appelée Column Qualifier. On pourra donc parler du couple (Column Qualifier, valeur) appelé également Cell.



L'ensemble de clé ou Column Qualifier que compose une ligne, est organisé en un groupe homogène appelé Column Family (il s'agit juste de regroupement d'un ensemble de clés). Ce regroupement permet de tracer une séparation sémantique entre les clés. Par exemple, pour une table Personne, on pourra créer 2 Column Family : - Identité composée des clés (Column Qualifier) : nom, prénom, age ; - Adresse composée : numéro de la rue, nom de la rue, code postal, ville.  Une ligne Hbase est donc composée d'un ensemble de Column Family qui est composée d'un ensemble de Cell (couple clé-valeur ou Column Qualifier, valeur). 



Les Column Family ne sont pas aussi dynamiques que Column Qualifier. Elles doivent être définies lors de la création de la table et ne doivent pratiquement pas changer en cours de route. À l’opposé, les Column Qualifier peuvent être instanciées et ajoutées aux tables (aux Column Family) à tout moment.

Parmi les concepts intéressants de HBase, on retrouve le versonning des valeurs. En effet, une clé (Column Qualifier) peut avoir plusieurs valeurs avec une version associée à chaque valeur. Les versions sont identifiées par leur timestamp (de type long). Le nombre de versions est configuré lors de la définition d'une Column Family. Par défaut, ce nombre est égal à trois. 


Exemple :




La suite de cet article est de vous présenter une introduction HBase SHELL & HBase JAVA API pour effectuer de requête ...

vendredi 12 décembre 2014

Maven en ligne de commande : Exécution d'une classe/méthode de test spécifique

Comment exécuter une classe de test avec maven :

maven -Dtest=ClassTest test

On peut également spécifier une méthode :

maven -Dtest=ClassTest#test_method test