HBase com Java

HBase com Java

*1. Visão geral *

Neste artigo, veremos a biblioteca Java Client do banco de dados HBase. O HBase é um banco de dados distribuído que usa o sistema de arquivos Hadoop para armazenar dados.

Criaremos um cliente de exemplo Java e uma tabela à qual adicionaremos alguns registros simples.

===* 2. Estrutura de dados do HBase *

No HBase, os dados são agrupados em famílias de colunas. Todos os membros da coluna de uma família de colunas têm o mesmo prefixo.

Por exemplo, as colunas family1: qualifier1 e family1: qualifier2 são membros da família de colunas family1. Todos os membros da família da coluna são armazenados juntos no sistema de arquivos.

Dentro da família de colunas, podemos colocar uma linha com um qualificador especificado. Podemos pensar em um qualificador como uma espécie do nome da coluna.

Vamos ver um exemplo de registro do 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'
}

Temos duas famílias de colunas, cada uma delas com três qualificadores com alguns dados de célula. Cada linha tem uma chave de linha - é um identificador de linha exclusivo. Usaremos a tecla de linha para inserir, recuperar e excluir os dados.

===* 3. Dependência do Maven do cliente HBase *

Antes de nos conectarmos ao HBase, precisamos adicionar https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.apache.hbase%22%20AND%20a%3A%22hbase- cliente% 22 [hbase-client] e _https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.apache.hbase%22%20AND%20a%3A%22hbase%22 [ hbase] _ dependências:

<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-client</artifactId>
    <version>${hbase.version}</version>
</dependency>
<dependency>
     <groupId>org.apache.hbase</groupId>
     <artifactId>hbase</artifactId>
     <version>${hbase.version}</version>
</dependency>

===* 4. Configuração do HBase *

Precisamos configurar o HBase para poder conectar a partir de uma biblioteca cliente Java. A instalação está fora do escopo deste artigo, mas você pode conferir algumas das instalações do HBase guides online.

Em seguida, precisamos iniciar um mestre do HBase localmente executando:

hbase master start

===* 5. Conectando-se ao HBase a partir de Java *

Para conectar programaticamente do Java ao HBase, precisamos definir um arquivo de configuração XML. Iniciamos nossa instância do HBase no localhost, portanto, precisamos inseri-la em um arquivo de configuração:

<configuration>
    <property>
        <name>hbase.zookeeper.quorum</name>
        <value>localhost</value>
    </property>
    <property>
        <name>hbase.zookeeper.property.clientPort</name>
        <value>2181</value>
    </property>
</configuration>

Agora precisamos apontar um cliente HBase para esse arquivo de configuração:

Configuration config = HBaseConfiguration.create();

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

Em seguida, estamos verificando se uma conexão com o HBase foi bem-sucedida - no caso de uma falha, a MasterNotRunningException será lançada:

HBaseAdmin.checkHBaseAvailable(config);

===* 6. Criando uma estrutura de banco de dados *

Antes de começarmos a adicionar dados ao HBase, precisamos criar a estrutura de dados para inserir linhas. Criaremos uma tabela com duas famílias de colunas:

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

Primeiramente, precisamos criar uma conexão com o banco de dados e obter o objeto admin, que usaremos para manipular uma estrutura de banco de dados:

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

Em seguida, podemos criar uma tabela passando uma instância da classe HTableDescriptor para um método createTable () _ no objeto _admin:

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

===* 7. Adicionando e recuperando elementos *

Com a tabela criada, podemos adicionar novos dados criando um objeto Put e chamando um método put () _ no objeto _Table:

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

A recuperação da linha criada anteriormente pode ser obtida usando uma classe Get:

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

O row1 é um identificador de linha - podemos usá-lo para recuperar uma linha específica do banco de dados. Ao ligar para:

Bytes.bytesToString(value)

o resultado retornado será anteriormente o cell_data. inserido

===* 8. Digitalização e filtragem *

Podemos verificar a tabela, recuperando todos os elementos dentro de um determinado qualificador usando um objeto Scan (observe que ResultScanner estende Closable, certifique-se de chamar _close () _ nela quando terminar):

Scan scan = new Scan();
scan.addColumn(family1.getBytes(), qualifier1);

ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
    System.out.println("Found row: " + result);
}

Essa operação imprimirá todas as linhas dentro de um qualifier1 com algumas informações adicionais, como timestamp:

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

Podemos recuperar registros específicos usando filtros.

Em primeiro lugar, estamos criando dois filtros. O filter1 especifica que a consulta de verificação recuperará elementos maiores que row1, _ e _filter2 especifica que estamos interessados ​​apenas em linhas que tenham um qualificador igual a qualifier1:

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

Em seguida, podemos obter um conjunto de resultados de uma consulta Scan:

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);
    }
}

Ao criar um FilterList, passamos por um Operator.MUST_PASS_ALL - significa que todos os filtros devem ser satisfeitos. Podemos escolher uma Operation.MUST_PASS_ONE se apenas um filtro precisar ser satisfeito. No conjunto resultante, teremos apenas linhas que correspondem aos filtros especificados.

===* 9. Excluindo linhas *

Por fim, para excluir uma linha, podemos usar uma classe Delete:

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

Estamos excluindo um row1 que reside dentro de uma family1.

===* 10. Conclusão*

Neste tutorial rápido, focamos na comunicação com um banco de dados HBase. Vimos como se conectar ao HBase a partir da biblioteca do cliente Java e como executar várias operações básicas.

A implementação de todos esses exemplos e trechos de código pode ser encontrada no GitHub project; como é um projeto do Maven, deve ser fácil importar e executar como está.