HBase con Java

1. Panoramica

In questo articolo, esamineremo la libreria client Java del database HBase . HBase è un database distribuito che utilizza il file system Hadoop per la memorizzazione dei dati.

Creeremo un client di esempio Java e una tabella a cui aggiungeremo alcuni semplici record.

2. Struttura dati HBase

In HBase, i dati vengono raggruppati in famiglie di colonne. Tutti i membri di colonna di una famiglia di colonne hanno lo stesso prefisso.

Ad esempio, le colonne family1: qualifier1 e family1 : qualifier2 sono entrambe membri della famiglia di colonne family1 . Tutti i membri della famiglia di colonne vengono memorizzati insieme nel filesystem.

All'interno della famiglia di colonne, possiamo inserire una riga con un qualificatore specificato. Possiamo pensare a un qualificatore come una sorta di nome di colonna.

Vediamo un record di esempio da Hbase:

Family1:{ 'Qualifier1':'row1:cell_data', 'Qualifier2':'row2:cell_data', 'Qualifier3':'row3:cell_data' } Family2:{ 'Qualifier1':'row1:cell_data', 'Qualifier2':'row2:cell_data', 'Qualifier3':'row3:cell_data' }

Abbiamo due famiglie di colonne, ciascuna con tre qualificatori con alcuni dati di cella. Ogni riga ha una chiave di riga: è un identificatore di riga univoco. Useremo la chiave di riga per inserire, recuperare ed eliminare i dati.

3. Dipendenza Maven client HBase

Prima di connetterci a HBase, dobbiamo aggiungere le dipendenze hbase-client e hbase :

 org.apache.hbase hbase-client ${hbase.version}   org.apache.hbase hbase ${hbase.version} 

4. Configurazione HBase

Dobbiamo configurare HBase per poterci connettere da una libreria client Java ad esso. L'installazione non rientra negli scopi di questo articolo, ma puoi consultare alcune delle guide all'installazione di HBase online.

Successivamente, dobbiamo avviare un master HBase localmente eseguendo:

hbase master start

5. Connessione a HBase da Java

Per connettersi a livello di codice da Java a HBase, è necessario definire un file di configurazione XML. Abbiamo avviato la nostra istanza HBase su localhost, quindi dobbiamo inserirla in un file di configurazione:

  hbase.zookeeper.quorum localhost   hbase.zookeeper.property.clientPort 2181   

Ora dobbiamo puntare un client HBase a quel file di configurazione:

Configuration config = HBaseConfiguration.create(); String path = this.getClass() .getClassLoader() .getResource("hbase-site.xml") .getPath(); config.addResource(new Path(path)); 

Successivamente, stiamo controllando se una connessione a HBase ha avuto esito positivo: in caso di errore, verrà generata l' eccezione MasterNotRunningException :

HBaseAdmin.checkHBaseAvailable(config);

6. Creazione di una struttura di database

Prima di iniziare ad aggiungere dati a HBase, dobbiamo creare la struttura dati per l'inserimento di righe. Creeremo una tabella con due famiglie di colonne:

private TableName table1 = TableName.valueOf("Table1"); private String family1 = "Family1"; private String family2 = "Family2";

In primo luogo, dobbiamo creare una connessione al database e ottenere l' oggetto admin , che useremo per manipolare una struttura del database:

Connection connection = ConnectionFactory.createConnection(config) Admin admin = connection.getAdmin();

Quindi, possiamo creare una tabella passando un'istanza della classe HTableDescriptor a un metodo createTable () sull'oggetto admin :

HTableDescriptor desc = new HTableDescriptor(table1); desc.addFamily(new HColumnDescriptor(family1)); desc.addFamily(new HColumnDescriptor(family2)); admin.createTable(desc);

7. Aggiunta e recupero di elementi

Con la tabella creata, possiamo aggiungervi nuovi dati creando un oggetto Put e chiamando un metodo put () sull'oggetto Table :

byte[] row1 = Bytes.toBytes("row1") Put p = new Put(row1); p.addImmutable(family1.getBytes(), qualifier1, Bytes.toBytes("cell_data")); table1.put(p);

Il recupero della riga creata in precedenza può essere ottenuto utilizzando una classe Get :

Get g = new Get(row1); Result r = table1.get(g); byte[] value = r.getValue(family1.getBytes(), qualifier1);

La riga1 è un identificatore di riga: possiamo usarlo per recuperare una riga specifica dal database. Quando si chiama:

Bytes.bytesToString(value)

il risultato restituito sarà precedentemente il cell_data inserito .

8. Scansione e filtraggio

Possiamo scansionare la tabella, recuperando tutti gli elementi all'interno di un dato qualificatore usando un oggetto Scan (nota che ResultScanner estende Closable , quindi assicurati di chiamare close () su di esso quando hai finito):

Scan scan = new Scan(); scan.addColumn(family1.getBytes(), qualifier1); ResultScanner scanner = table.getScanner(scan); for (Result result : scanner) { System.out.println("Found row: " + result); } 

Quell'operazione stamperà tutte le righe all'interno di un qualificatore1 con alcune informazioni aggiuntive come il timestamp:

Found row: keyvalues={Row1/Family1:Qualifier1/1488202127489/Put/vlen=9/seqid=0}

Possiamo recuperare record specifici utilizzando i filtri.

Innanzitutto, stiamo creando due filtri. Le Filter1 specifica tale query scansione recuperare elementi che sono maggiori di row1, e filtro2 specifica che interessa solo le righe che hanno una qualificazione pari alla qualifier1 :

Filter filter1 = new PrefixFilter(row1); Filter filter2 = new QualifierFilter( CompareOp.GREATER_OR_EQUAL, new BinaryComparator(qualifier1)); List filters = Arrays.asList(filter1, filter2);

Then we can get a result set from a Scan query:

Scan scan = new Scan(); scan.setFilter(new FilterList(Operator.MUST_PASS_ALL, filters)); try (ResultScanner scanner = table.getScanner(scan)) { for (Result result : scanner) { System.out.println("Found row: " + result); } }

When creating a FilterList we passed an Operator.MUST_PASS_ALL – it means that all filters must be satisfied. We can choose an Operation.MUST_PASS_ONE if only one filter needs to be satisfied. In the resulting set, we will have only rows that matched specified filters.

9. Deleting Rows

Finally, to delete a row, we can use a Delete class:

Delete delete = new Delete(row1); delete.addColumn(family1.getBytes(), qualifier1); table.delete(delete);

We're deleting a row1 that resides inside of a family1.

10. Conclusion

In this quick tutorial, we focused on communicated with a HBase database. We saw how to connect to HBase from the Java client library and how to run various basic operations.

L'implementazione di tutti questi esempi e frammenti di codice può essere trovata nel progetto GitHub; questo è un progetto Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.