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
Прежде чем мы подключимся к HBase, нам нужно добавить зависимости 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 в Интернете .
Затем нам нужно запустить мастер HBase локально, выполнив:
hbase master start
5. Подключение к HBase из Java
Чтобы программно подключиться из Java к HBase, нам нужно определить файл конфигурации XML. Мы запустили наш экземпляр HBase на локальном хосте, поэтому нам нужно ввести его в файл конфигурации:
<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";
Во-первых, нам нужно создать подключение к базе данных и получить объект администратора
, который мы будем использовать для управления структурой базы данных:
Connection connection = ConnectionFactory.createConnection(config)
Admin admin = connection.getAdmin();
Затем мы можем создать таблицу, передав экземпляр класса HTableDescriptor в метод
createTable () объекта
администратора
:
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);
}
Эта операция напечатает все строки внутри квалификатора1
с некоторой дополнительной информацией, такой как отметка времени:
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 = 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, поэтому его легко импортировать и запускать как есть.