HBase с Java

1. Обзор

В этой статье мы рассмотрим библиотеку клиента Java базы данных HBase HBase - это распределенная база данных, которая использует файловую систему Hadoop для хранения данных.

Мы создадим пример клиента Java и таблицу, в которую добавим несколько простых записей.

2. Структура данных HBase

В HBase данные сгруппированы в семейства столбцов. Все члены столбцов семейства столбцов имеют одинаковый префикс.

Например, столбцы family1: qualifier1 и family1: qualifier2 оба являются членами семейства столбцов family1 . Все члены семейства столбцов хранятся вместе в файловой системе.

Внутри семейства столбцов мы можем поместить строку с указанным квалификатором. Мы можем думать о квалификаторе как о типе имени столбца.

Давайте посмотрим на пример записи из 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'
}

У нас есть два семейства столбцов, каждое из которых имеет три классификатора с некоторыми ячейками данных. У каждой строки есть ключ строки - это уникальный идентификатор строки.

Мы будем использовать ключ строки для вставки, извлечения и удаления данных.

3. Клиент HBase Maven Dependency

Перед подключением к HBase нам нужно добавить https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.apache.hbase%22%20AND%20a%3A%22hbase- client% 22[ hbase-client hbase зависимости:

<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. Настройка HBase

Нам нужно настроить HBase, чтобы иметь возможность подключаться к нему из клиентской библиотеки Java. Установка выходит за рамки данной статьи, но вы можете ознакомиться с некоторыми установками HBase guides online .

Далее нам нужно запустить мастер HBase локально, выполнив:

hbase master start

5. Подключение к HBase из Java

Для программного соединения из Java в HBase нам нужно определить файл конфигурации XML. Мы запустили наш экземпляр HBase на localhost, поэтому нам нужно ввести это в файл конфигурации:

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

Теперь нам нужно указать клиенту HBase на этот файл конфигурации:

Configuration config = HBaseConfiguration.create();

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

Далее мы проверяем, было ли соединение с HBase успешным - в случае сбоя будет сгенерировано MasterNotRunningException :

HBaseAdmin.checkHBaseAvailable(config);

6. Создание структуры базы данных

Прежде чем мы начнем добавлять данные в HBase, нам нужно создать структуру данных для вставки строк. Мы создадим одну таблицу с двумя семействами столбцов:

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

Во-первых, нам нужно создать соединение с базой данных и получить объект admin , который мы будем использовать для управления структурой базы данных:

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

Затем мы можем создать таблицу, передав экземпляр класса HTableDescriptor методу createTable () объекта admin :

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

7. Добавление и получение элементов

Создав таблицу, мы можем добавить в нее новые данные, создав объект Put и вызвав метод put () для объекта Table :

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

Получить ранее созданную строку можно с помощью класса Get :

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

Row1 - это идентификатор строки - мы можем использовать его для извлечения конкретной строки из базы данных. При звонке:

Bytes.bytesToString(value)

возвращенный результат будет ранее вставленным cell data.__

8. Сканирование и фильтрация

Мы можем сканировать таблицу, извлекая все элементы внутри заданного классификатора, используя объект Scan (обратите внимание, что ResultScanner расширяет Closable , поэтому обязательно вызовите close () , когда вы закончите):

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

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

Эта операция напечатает все строки внутри qualifier1 с некоторой дополнительной информацией, такой как отметка времени:

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

Мы можем получить конкретные записи с помощью фильтров.

Во-первых, мы создаем два фильтра. Filter1 указывает, что запрос сканирования будет извлекать элементы, которые больше, чем row1, и filter2 указывает, что нас интересуют только строки, которые имеют квалификатор, равный qualifier1 :

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

Затем мы можем получить набор результатов из запроса 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);
    }
}

При создании FilterList мы передали Operator.MUST PASS ALL - это означает, что все фильтры должны быть выполнены. Мы можем выбрать Operation.MUST PASS ONE , если требуется только один фильтр. В результирующем наборе у нас будут только строки, соответствующие указанным фильтрам.

9. Удаление строк

Наконец, чтобы удалить строку, мы можем использовать класс Delete :

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

Мы удаляем row1 , который находится внутри family1.

10. Заключение

В этом кратком руководстве мы сосредоточились на связи с базой данных HBase. Мы увидели, как подключиться к HBase из клиентской библиотеки Java и как выполнять различные основные операции.

Реализация всех этих примеров и фрагментов кода может быть найдена в проекте GitHub ; это проект Maven, поэтому его легко импортировать и запускать как есть.