Статьи

Обработка больших данных с помощью HBase. Часть 4. API Java

Примечание редактора: Обязательно ознакомьтесь с частью 1 и частью 2 .

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

Только что ознакомившись с высокоуровневой архитектурой HBase, теперь давайте рассмотрим клиентский API Java, поскольку именно так ваши приложения взаимодействуют с HBase. Как упоминалось ранее, вы также можете взаимодействовать с HBase с помощью нескольких разновидностей технологий RPC, таких как Apache Thrift и шлюз REST, но мы собираемся сосредоточиться на нативном Java API. Клиентские API предоставляют семантику DDL (язык определения данных) и DML (язык манипулирования данными), очень похожую на то, что вы найдете в SQL для реляционных баз данных. Предположим, мы собираемся хранить информацию о людях в HBase, и мы хотим начать с создания новой таблицы. В следующем листинге показано, как создать новую таблицу с помощью HBaseAdminкласса.

Configuration conf = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(conf);
HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf("people"));
tableDescriptor.addFamily(new HColumnDescriptor("personal"));
tableDescriptor.addFamily(new HColumnDescriptor("contactinfo"));
tableDescriptor.addFamily(new HColumnDescriptor("creditcard"));
admin.createTable(tableDescriptor);

peopleТаблица определена в предыдущем список содержит три семейства столбцов: personal, contactinfoи creditcard. Чтобы создать таблицу, вы создаете HTableDescriptorи добавляете одно или несколько семейств столбцов путем добавления HColumnDescriptorобъектов. Затем вы звоните, createTableчтобы создать таблицу. Теперь у нас есть таблица, поэтому давайте добавим некоторые данные. В следующем листинге показано, как использовать Putкласс для вставки данных о Джоне Доу, в частности, его имени и адреса электронной почты (для краткости опущена правильная обработка ошибок).

Configuration conf = HBaseConfiguration.create();
HTable table = new HTable(conf, "people");
Put put = new Put(Bytes.toBytes("doe-john-m-12345"));
put.add(Bytes.toBytes("personal"), Bytes.toBytes("givenName"), Bytes.toBytes("John"));
put.add(Bytes.toBytes("personal"), Bytes.toBytes("mi"), Bytes.toBytes("M"));
put.add(Bytes.toBytes("personal"), Bytes.toBytes("surame"), Bytes.toBytes("Doe"));
put.add(Bytes.toBytes("contactinfo"), Bytes.toBytes("email"), Bytes.toBytes("john.m.doe@gmail.com"));
table.put(put);
table.flushCommits();
table.close();

В приведенном выше листинге мы создаем Putуникальный ключ строки для конструктора. Затем мы добавляем значения, которые должны включать семейство столбцов, спецификатор столбца и значение в виде байтовых массивов . Как вы, наверное, заметили, служебный Bytesкласс HBase API часто используется; он предоставляет методы для преобразования в и из byte[]примитивных типов и строк. (Добавление статического импорта для этого toBytes()метода привело бы к сокращению большого количества стандартного кода.) Затем мы помещаем данные в таблицу, сбрасываем коммиты, чтобы гарантировать вступление в силу локально буферизованных изменений, и, наконец, закрываем таблицу. Обновление данных также осуществляется черезPutКласс точно так же, как показано в предыдущем листинге. В отличие от реляционных баз данных, в которых обновления должны обновлять целые строки, даже если изменился только один столбец, если вам нужно обновить только один столбец, то это все, что вы указываете в, Putа HBase будет обновлять только этот столбец. Существует также checkAndPutоперация, которая по существу является формой оптимистического управления параллелизмом — операция будет помещать новые данные только в том случае, если текущие значения соответствуют значениям, указанным клиентом.

Получение строки, которую мы только что создали, выполняется с использованием Getкласса, как показано в следующем листинге. (Начиная с этого момента, списки будут опускать шаблонный код для создания конфигурации, создания HTableвызовов, а также вызовов сброса и закрытия.)

Get get = new Get(Bytes.toBytes("doe-john-m-12345"));
get.addFamily(Bytes.toBytes("personal"));
get.setMaxVersions(3);
Result result = table.get(get);

Код в предыдущем листинге создает Getэкземпляр, предоставляющий ключ строки, который мы хотим найти. Затем мы используем addFamilyдля указания HBase, что нам нужны только данные из семейства personalстолбцов, что также сокращает объем работы, которую HBase должен выполнять при чтении информации с диска. Мы также указываем, что нам нужно до трех версий каждого столбца в нашем результате, возможно, чтобы мы могли перечислить исторические значения каждого столбца. Наконец, вызов getвозвращает Resultэкземпляр, который затем можно использовать для проверки всех возвращаемых значений столбца.

Во многих случаях вам нужно найти более одной строки. HBase позволяет вам делать это путем сканирования строк, как показано во второй части, которая показала использование сканирования в сеансе оболочки HBase. Соответствующий класс является Scanклассом. Вы можете указать различные параметры, такие как начальный и конечный ключи строки для сканирования, какие столбцы и семейства столбцов следует включить и максимальное количество версий для извлечения. Вы также можете добавить фильтры, которые позволят вам реализовать собственную логику фильтрации, чтобы еще больше ограничить возвращаемые строки и столбцы. Обычный вариант использования фильтров — это нумерация страниц. Например, нам может понадобиться сканировать всех людей, чья фамилия Смит, по одной странице (например, 25 человек) за раз. Следующий листинг показывает, как выполнить базовое сканирование.

Scan scan = new Scan(Bytes.toBytes("smith-"));
scan.addColumn(Bytes.toBytes("personal"), Bytes.toBytes("givenName"));
scan.addColumn(Bytes.toBytes("contactinfo"), Bytes.toBytes("email"));
scan.setFilter(new PageFilter(25));
ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
    // ...
}

В приведенном выше листинге мы создаем новый, Scanкоторый начинается с ключа строки, smith-и затем мы используем его addColumnдля ограничения возвращаемых столбцов (таким образом, уменьшая объем переноса диска, который должен выполнять HBase) до personal:givenNameи contactinfo:email. При PageFilterсканировании A ограничивается числом проверяемых строк до 25. (Альтернативой использованию фильтра страницы может быть указание ключа остановки строки при построении Scan.) Затем мы получаем a ResultScannerдля Scanтолько что созданного и выполняем цикл по результаты выполнения любых необходимых действий. Поскольку в HBase единственный метод извлечения нескольких строк данных — это сканирование по отсортированным ключам строк, очень важно, как вы проектируете значения ключей строк. Мы вернемся к этой теме позже.

Вы также можете удалить данные в HBase, используя Deleteкласс, аналогичный Putклассу, чтобы удалить все столбцы в строке (таким образом, удалив саму строку), удалить семейства столбцов, удалить столбцы или некоторую их комбинацию.

Обработка соединения

В приведенных выше примерах не было уделено большого внимания обработке соединений и RPC (удаленным вызовам процедур). HBase предоставляет HConnectionкласс, который предоставляет функциональность, аналогичную классам пула соединений, для совместного использования соединений, например, вы используете getTable()метод для получения ссылки на HTableэкземпляр. Существует также HConnectionManagerкласс, который вы получаете экземпляры HConnection. Подобно тому, как избегать сетевых обходов в веб-приложениях, важно эффективно управлять количеством RPC и количеством данных, возвращаемых при использовании HBase, и что-то следует учитывать при написании приложений HBase.

Заключение к части 4

В этой части мы использовали HBase Java API для создания peopleтаблицы, вставки нового человека и поиска информации о вновь вставленном человеке. Мы также использовали Scanкласс для сканирования peopleтаблицы людей с фамилией «Смит» и показали, как ограничить полученные данные и, наконец, как использовать фильтр для ограничения количества результатов.

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

Ссылки