Microsoft Azure изнутри

Hadoop и HDInsight: большие данные в Microsoft Azure

**Бруно Теркали
**Рикардо Виллалобос

Bruno Terkaly, Ricardo VillalobosДавайте начнем со смелого утверждения: «Если вы, ваша начинающая компания или предприятие, где вы работаете, не сохраняете массивные объемы данных на диск для текущего и будущего анализа, вы теряете эффективность как технический руководитель». Разве не глупо основывать важные бизнес-решения только на интуиции, пренебрегая реальными количественными показателями?

Есть много причин, по которым большие данные (big data) столь повсеместно распространены. Во-первых, это удивительно дешевый способ собирать и хранить данные в любой форме — структурированной или неструктурированной — особенно с помощью таких продуктов, как сервисы Microsoft Azure Storage. Во-вторых, использовать облако, чтобы обеспечить необходимые вычислительные ресурсы для анализа этих данных, очень выгодно с экономической точки зрения. Наконец, большие данные дают бизнесу значительное преимущество в конкурентной борьбе, поскольку позволяют извлекать новую информацию из огромных объемов неструктурированных данных. Цель этой статьи — показать, как можно решать трудные задачи обработки больших данных на платформе Microsoft Azure, в частности Microsoft Azure HDInsight Service.

Едва ли не каждый день в ИТ-прессе появляется какая-нибудь ажиотажная статья (а иногда и в средствах массовой информации) о больших данных. Под большими данными подразумеваются просто наборы данных, столь большие и сложные, что их трудно обработать традиционными средствами, например с помощью кубов данных, денормализованных реляционных таблиц, механизмов пакетного извлечения, преобразования и загрузки (extract, transform and load, ETL) и др. Сторонники использования больших данных говорят об извлечении научных и бизнес-знаний из петабайтов неструктурированных данных, которые могут поступать из множества источников: датчиков, веб-журналов, мобильных устройств и Интернета вещей (Internet of Things, IoT) (технологий, основанных на радиочастотной идентификации [radio-frequency identification, RFID], таких как коммуникации ближнего радиуса действия, штрих-коды, коды Quick Response [QR] и цифровые водяные знаки). IoT меняет само понятие «большой» — теперь мы говорим об экзабайтах данных ежедневно!

Оправдана ли вся эта шумиха? Microsoft определенно считает, что да, и сделала крупную ставку на большие данные. Во-первых, большие данные позволяют вырабатывать более эффективные рыночные стратегии и принимать решения не на интуитивных ощущениях, а на основе анализа реального поведения потребителей. Во-вторых, руководители компаний могут улучшить стратегические решения, такие как добавление новой функциональности в приложение или веб-сайт, поскольку у них появляется возможность изучить результаты дистанционных измерений и данные по использованию приложений, выполняемых на множестве устройств. В-третьих, это помогает финансовым сервисам распознавать попытки мошенничества и оценивать риски. Наконец, хотя вы, возможно, не осознаете этого, именно технологии больших данных обычно применяются для создания механизмов выработки рекомендаций (вроде Netflix). Рекомендации часто предлагаются в виде веб-сервиса или в рамках крупных компаний, способствуя скорейшему принятию бизнес-решений. По-настоящему интеллектуальные предприятия сегодня собирают данные, даже не зная, какого рода ответы на основе этих данных им понадобятся завтра.

На самом деле большие данные подразумевают анализ данных, который практикуется уже достаточно давно. Хотя огромных хранилища данных всегда «просеивались» и анализировались в поисках крупиц ценной информации, сегодняшний мир отличается колоссальным разнообразием неструктурированных данных. К счастью, такие продукты, как Microsoft Azure, открывают широкие возможности для экономии, позволяя практически кому угодно наращивать свои вычислительные мощности и применять их обработке очень больших объемов данных и делать все это в одном информационном центре. Ученые в области анализа данных описывают этот новый феномен как три «V»: velocity (скорость), volume (объем) и variety (разнообразие). Еще никогда данные не генерировались с такими скоростью, объемами и отсутствием определенной структуры.

Мир больших данных включает огромную и полную жизни экосистему, но один проект с открытым исходным кодом все доминирует над всеми остальными, и это Hadoop. Hadoop является стандартом де факто для «перемалывания» распределенных данных. Отличное введение в Hadoop вы найдете по ссылке bit.ly/PPGvDP: «Hadoop предоставляет инфраструктуру MapReduce для написания приложений, которые обрабатывают большие объемы структурированных и полу-структурированных данных, распараллеливая их по крупным кластерам машин и обеспечивая высокую надежность и отказоустойчивость». Кроме того, когда вы получше узнаете эту область, вы скорее всего согласитесь с точкой зрения Мэтта Уинклера (Matt Winkler) (главный руководитель проекта HDInsight) насчет того, что Hadoop является «экосистемой связанных проектов поверх основного распределенного хранилища и инфраструктуры MapReduce». Пако Натан (Paco Nathan), один из руководителей Concurrent и участник проекта с открытым исходным кодом Cascading (cascading.org), добавляет: «уровни абстракции позволяют людям эффективно использовать Hadoop, ничего не зная о его начинке».

Модель MapReduce

MapReduce — модель программирования, используемая при обработке огромных наборов данных; по сути, это «язык ассемблера» для Hadoop, поэтому знание того, что она делает, крайне важно для понимания Hadoop. Алгоритмы MapReduce пишутся на Java и разделяют входной набор данных на независимые части, обрабатываемые задачами карты (map tasks) полностью параллельно. Инфраструктура сортирует вывод карт (maps), который потом подается как ввод для задач предварительной обработки (reduce tasks). Как правило, ввод и вывод задания (job) хранятся в файловой системе. Инфраструктура берет на себя планирование задач, их отслеживание и повторное выполнение задач, завершившихся неудачно.

В конечном счете большинству разработчиков не приходится писать низкоуровневый Java-код для MapReduce. Вместо этого они пользуются продвинутым инструментарием, который абстрагирует сложности MapReduce, например Hive или Pig. Чтобы получить представление об этой абстракции, мы заглянем в низкоуровневый Java-код MapReduce и посмотрим, как высокоуровневый механизм запросов Hive, поддерживаемый HDInsight, значительно упрощает всю работу.

Почему HDInsight?

HDInsight — реализация Apache Hadoop, выполняемая в глобально распределенных информационных центрах Microsoft. Это сервис, который позволяет вам в считанные минуты формировать кластер Hadoop, когда он нужен, и расформировывать его по завершении ваших заданий MapReduce. Как люди, хорошо знающие Microsoft Azure изнутри, мы считаем, что у HDInsight есть пара ключевых преимуществ. Первое заключается в том, что он полностью основан на Apache, а не является специальной версией от Microsoft, т. е. по мере развития Hadoop в Microsoft будут использовать более новые версии. Более того, Microsoft — основной участник проекта Hadoop/Apache и предоставила множество своих «ноу-хау» в оптимизации запросов для Hive.

Второе преимущество в том, что HDInsight бесшовно интегрируется с Microsoft Azure Blobs, механизмами для хранения больших объемов неструктурированных данных, к которым можно обращаться из любой точки мира по HTTP или HTTPS. HDInsight также позволяет сохранять метаданные определений таблиц в SQL Server, чтобы после закрытия кластера вам не приходилось с нуля заново создавать свои модели данных.

На рис. 1 схематически показана поддержка Hadoop на платформе Microsoft Azure.

Экосистема Hadoop в Microsoft Azure
Рис. 1. Экосистема Hadoop в Microsoft Azure

Hadoop in Microsoft Azure Hadoop в Microsoft Azure
Microsoft Azure Microsoft Azure
Storage Options Available Доступные виды хранилищ
Blobs Blobs
Tables Tables
SQL SQL
Other Другие
Microsoft Azure Virtual Machines (with Hadoop) Виртуальные машины Microsoft Azure (с Hadoop)
Operating System = CentOS Операционная система = CentOS
Java SDK Version 1.6 Java SDK версии 1.6
Hadoop Framework Version 2.0 Hadoop Framework версии 2.0
Hadoop Command Window Командное окно Hadoop
HDInsight (Hadoop as a Service) HDInsight (Hadoop как сервис)
Your Clusters Ваши кластеры
Hadoop Command Window Командное окно Hadoop
HDInsight Portal HDInsight Portal
Node 1 Узел 1
Node 2 Узел 2
Node 3 Узел 3
Node 4 Узел 4

На верхнем уровне находится система Microsoft Azure Storage, которая предоставляет безопасное и надежное хранилище и включает встроенные средства территориально распределенной репликации для поддержания избыточности ваших данных между регионами. Microsoft Azure Storage содержит множество мощных и гибких механизмов хранения, таких как Tables (NoSQL-хранилище пар «ключ-значение»), база данных SQL, Blobs и др. Она поддерживает RESTful API, который позволяет любому клиенту выполнять CRUD-операции (create, read, update, delete) с текстовыми и двоичными данными, например с видео-, аудиозаписями и изображениями. Это означает, что любой клиент с поддержкой HTTP, может взаимодействовать с этой системой. Hadoop напрямую взаимодействует с Blobs, но не ограничивает вас в использовании других механизмов хранения в вашем приложении.

Вторая ключевая область — поддержка в Microsoft Azure виртуальных машин (VM) под управлением Linux. Hadoop работает в Linux и использует Java, позволяя вам настраивать собственный одно- или многоузловой кластер Hadoop. Это может дать колоссальную экономию денег и значительно повысить производительность, поскольку одна VM в Microsoft Azure очень экономична. При желании вы можете вручную создать собственный многоузловой кластер, но это нетривиальная задача и излишне, когда вы просто пытаетесь проверить некоторые базовые алгоритмы.

Подготовка своего кластера Hadoop облегчает изучение и разработку приложений Hadoop. Более того, проделав это собственноручно, вы получаете бесценное представление о внутреннем устройстве и принципах работы Hadoop. Если вы хотите узнать, как это делается, см. публикацию в блоге «How to Install Hadoop on a Linux-Based Microsoft Azure Virtual Machine» (bit.ly/1am85mU).

Конечно, как только вам понадобится более крупный кластер, вы предпочтете воспользоваться преимуществами HDInsight, который на данный момент доступен в режиме предварительного просмотра. Для начала зайдите на портал Microsoft Azure (bit.ly/12jt5KW) и войдите под своей учетной записью. Затем выберите Data Services | HDInsight | Quick Create. Вам будет предложено указать имя кластера, количество вычислительных узлов (в настоящее время от четырех до 32) и учетную запись хранилища, с которой вы хотите связать этот кластер. Местонахождение вашей учетной записи хранилища определяет местоположение вашего кластера. Наконец, щелкните CREATE HDINSIGHT CLUSTER. На подготовку кластера уйдет 10–15 минут, и это время не связано с размером кластера.

Заметьте, что кластер HDInsight можно создать и управлять им программным способом, используя Windows PowerShell, а также кросс-платформенный инструментарий в системах на основе Linux и Mac. Большая часть функциональности в интерфейсе командной строки (command-line interface, CLI) также доступна на простом в использовании портале, который позволяет управлять кластером, в том числе выполнением заданий в кластере. Вы можете скачать Microsoft Azure PowerShell и CLI для Mac и Linux по ссылке bit.ly/ZueX9Z. Затем установите свою VM под управлением CentOS (это одна из версий Linux), а также Java SDK и Hadoop.

Исследуем Hadoop

Чтобы поэкспериментировать с Hadoop и оценить его мощь, мы решили использовать открытые данные с сайта data.sfgov.org. Точнее, мы скачали файл, содержащий данные по правонарушениям в Сан-Франциско за предыдущие три месяца, и задействовали его в том виде, как он есть. Этот файл включает более 33 000 записей (сравнительно мало по меркам больших данных), извлеченных из системы генерации отчетов о случаях правонарушений, зафиксированных полицией Сан-Франциско (SFPD Crime Incident Reporting system). Наша цель — провести простой анализ, например определить количество и тип случаев правонарушений. В табл. 1 показана часть вывода от задания Hadoop, суммирующего данные о правонарушениях по типу.

Табл. 1. Данные о правонарушениях, суммированные по типу

Крупные кражи из запертых автомашин 2617
Бандитизм 1623
Проблемы с водительскими правами 1230
Случаи, потребовавшие вызова скорой помощи 1195
Утраченное имущество 1083

Код на рис. 2 суммирует данные по трем месяцам. Входной файл содержит более 30 000 записей, а выходной — всего тысячу. Первые пять из этой 1000 записей приведены в табл. 1.

Рис. 2. Java-код MapReduce, суммирующий данные о правонарушениях

// CrimeCount.java
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapred.*;
import org.apache.hadoop.util.*;
// Этот код основан на стандартных примерах подсчета слов,
// которые можно найти почти где угодно. Мы модифицировали
// функцию map, чтобы была возможность агрегации данных
// по типу правонарушений. Функция reduce, равно как и main,
// не модифицирована – изменено лишь имя задания.
public class CrimeCount {
public static class Map extends MapReduceBase implements 
  Mapper<LongWritable, Text, Text, IntWritable> {
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
    private String mytoken = null;
    public void map(LongWritable key, Text value,
                    OutputCollector<Text, IntWritable> output,
                    Reporter reporter) throws IOException {
      // Считываем одну строку из входного файла
      String line = value.toString();
      // Разбираем строку на отдельные поля
      String[] myarray = line.split(",");
      // Проверяем, чтобы было не менее трех полей
      if(myarray.length >= 2){
        // Получаем третье поле и увеличиваем счетчик
        // соответствующих правонарушений
        // (т. е. LOST PROPERTY найдено, поэтому добавляем 1)
        mytoken = myarray[2];
        word.set(mytoken);
        // Добавляем в вывод пару "ключ-значение"
        output.collect(word, one);
      }
    }
  // Сравнительно универсальная реализация reduce
  public static class Reduce extends MapReduceBase implements Reducer<Text,
    IntWritable, Text, IntWritable> {
    public void reduce(Text key, Iterator<IntWritable> values,
                               OutputCollector<Text,
                               IntWritable> output,
                               Reporter reporter) throws IOException {
      // Перебираем агрегатные пары "ключ-значение"
      int sum = 0;
      while (values.hasNext()) {
        sum += values.next().get();
      }
      output.collect(key, new IntWritable(sum));
    }
  }
  // Запускаем задание MapReduce, указывая map и reduce,
  // а также входные и выходные параметры
  public static void main(String[] args) throws Exception {
    JobConf conf = new JobConf(CrimeCount.class);
    conf.setJobName("crimecount");
    conf.setOutputKeyClass(Text.class);
    conf.setOutputValueClass(IntWritable.class);
    conf.setMapperClass(Map.class);
    conf.setCombinerClass(Reduce.class);
    conf.setReducerClass(Reduce.class);
    conf.setInputFormat(TextInputFormat.class);
    conf.setOutputFormat(TextOutputFormat.class);
    FileInputFormat.setInputPaths(conf, new Path(args[0]));
    FileOutputFormat.setOutputPath(conf, new Path(args[1]));
    JobClient.runJob(conf);
  }
}

Сохранив код с рис. 2 как CrimeCount.java, скомпилируйте, упакуйте и передайте задание Hadoop. На рис. 3 содержатся инструкции для копирования входного файла с данными о правонарушениях в Hadoop Distributed File System (HDFS), компиляции CrimeCount.java, создания файла crimecount.jar, выполнения задания Hadoop (с использованием crimecount.jar) и отображения результатов, т. е. выходных данных. Чтобы скачать весь исходный код, зайдите на sdrv.ms/16kKJKh и щелкните правой кнопкой мыши папку CrimeCount.

Рис. 3. Компиляция, упаковка и выполнение задания Hadoop

# Создать папку для входного файла
hadoop fs -mkdir /tmp/hadoopjob/crimecount/input
# Скопировать файл данных в эту папку
hadoop fs -put SFPD_Incidents.csv
  /tmp/hadoopjob/crimecount/input
# Создать папку для выходных Java-классов
mkdir crimecount_classes
# Скомпилировать исходный код на Java
javac -classpath /usr/lib/hadoop/hadoop-common-2.0.0
  -cdh4.3.0.jar:/usr/lib/hadoop-0.20-mapreduce/hadoop
  -core-2.0.0-mr1-cdh4.3.0.jar -d crimecount_classes
  CrimeCount.java
# Создать JAR-файл из скомпилированного Java-кода
jar -cvf crimecount.jar -C crimecount_classes/ .
# Отправить этот файл как задание Hadoop, передав путь
# к классам, а также к папкам input и output.
# Примечание: в HDInsight можно использовать
# \"asv:///SFPD_Incidents.csv,\" вместо
# \"/tmp/hadoopjob/crimecount/input\", если входной файл
# (SFPD_Incidents.csv) загружен в Microsoft Azure Storage.
hadoop jar crimecount.jar org.myorg.CrimeCount
  /tmp/hadoopjob/crimecount/input
  /tmp/hadoopjob/crimecount/output
# Показать вывод (результаты) из папки output
hadoop fs -cat /tmp/hadoopjob/crimecount/output/part-00000

Теперь у вас есть представление, из каких кусочков состоит минимальная среда Hadoop, а также как выглядит Java-код MapReduce и как он в конечном счете отправляется в виде задания Hadoop из командной строки. Скорее всего в некий момент вам потребуется сформировать кластер для выполнения каких-то больших заданий, а затем завершить его, используя более высокоуровневый инструментарий вроде Hive или Pig. Именно это и делает HDInsight с помощью встроенной поддержки Pig и Hive.

Создав кластер, вы можете работать в командной строке Hadoop или использовать портал для выдачи запросов Hive и Pig. Преимущество этих запросов в том, что вам никогда не придется углубляться в Java и модифицировать MapReduce-функции, выполнять компиляцию и упаковку или запускать задание Hadoop с помощью файла .jar. Хотя вы можете обращаться к ведущему узлу кластера Hadoop и выполнять эти задачи (написав, скомпилировав и упаковав Java-код в файл .jar и использовав этот файл для выполнения как задания Hadoop), такой подход не оптимален для большинства пользователей Hadoop — он слишком низкоуровневый.

Самый продуктивный способ выполнения заданий MapReduce — применение портала Microsoft Azure в HDInsight и выдача запросов Hive, исходя из того, что использование Pig менее подходяще с технической точки зрения. Вы можете рассматривать Hive как более высокоуровневый инструментарий, который абстрагирует сложности написания MapReduce-функций на Java. На самом деле это не более чем SQL-подобный скриптовый язык. Запросы, написанные на Hive, компилируются в Java-функции MapReduce. Более того, поскольку Microsoft внесла значительный вклад в оптимизацию кода для Hive в проекте Apache Hadoop, запросы, написанные на Hive, скорее всего будут лучше оптимизированы и будут выполняться эффективнее, чем Java-код, написанный вручную. Отличное учебное пособие по этой тематике вы найдете по ссылке bit.ly/Wzlfbf.

Экосистема Hadoop

Отказавшись от низкоуровневого написания заданий MapReduce на Java, вы откроете невероятную, высокоразвитую экосистему инструментария, которая значительно расширяет возможности Hadoop. Например, Cloudera и Hortonworks являются успешными компаниями в области образования и консалтинговых услуг с бизнес-моделями, построенными на продуктах Hadoop. Многие проекты с открытым исходным кодом предоставляют дополнительные возможности, такие как машинное обучение (ML), SQL-подобные механизмы запросов, поддерживающие суммирование данных и специализированные запросы (Hive), поддержка языка для управления потоками данных (Pig) и многое другое. Вот лишь несколько проектов, на которые стоит обратить внимание: Sqoop, Pig, Apache Mahout, Cascading и Oozie. Microsoft тоже предлагает множество инструментов, в том числе Excel с PowerPivot, Power View и ODBC-драйверы, которые позволяют Windows-приложениям выдавать запросы к данным Hive. Зайдите на bit.ly/WIeBeq, чтобы получить наглядное представление о восхитительной экосистеме Hadoop.

Весь Java- и скриптовый код, представленный нами ранее, можно заменить компактным кодом, показанным на рис. 4. Просто замечательно, что с помощью трех строк кода на Hive можно добиться тех же (или даже лучших) результатов, чем при использовании всего ранее приведенного кода.

Рис. 4. Код Hive-запроса для выполнения алгоритма MapReduce

# Hive проделывает замечательную работу, представляя исходные
# хранилища данных Hadoop как реляционные таблицы, чтобы
# вы могли создавать SQL-подобные выражения
# Создаем псевдотаблицу для загрузки и запроса данных
CREATE TABLE sfpdcrime(
IncidntNum string,
Category string,
Descript string,
DayOfWeek string,
CrimeDate string,
CrimeTime string,
PdDistrict string,
Resolution string,
Address string,
X string,
Y string,
CrimeLocation string) ROW FORMAT DELIMITED FIELDS  TERMINATED BY ',';
# Загружаем данные в таблицу
LOAD DATA INPATH 'asv://sanfrancrime@brunoterkaly.blob.core.windows.net/SFPD_Incidents.csv' OVERWRITE INTO TABLE sfpdcrime;
 OVERWRITE INTO TABLE sfpdcrime;
select count(*) from sfpdcrime;
# Специализированный запрос для агрегации и суммирования
# по типам правонарушений
SELECT Descript, COUNT(*) AS cnt FROM sfpdcrime GROUP BY Descript
order by cnt desc;

На рис. 4 следует отметить несколько важных моментов. Прежде всего обратите внимание на то, что эти команды похожи на привычные SQL-выражения, позволяя вам создавать табличные структуры, в которые можно загружать данные. Что особенно интересно, вы можете загружать данные из сервисов Microsoft Azure Storage. Также обратите внимание на префикс «asv» в выражении загрузки на рис. 4. ASV — это аббревиатура от Azure Storage Vault, и вы можете использовать ASV как механизм хранения для передачи входных данных в задания Hadoop. Вероятно, вы помните, что при подготовке кластера HDInsight вы указывали одну или более специфических учетных записей сервисов Microsoft Azure Storage. Возможность применять сервисы Microsoft Azure Storage в HDInsight кардинально повышает удобство использования и эффективность управления и выполнения заданий Hadoop.

В этой статье мы дали вам лишь поверхностное представление о Hadoop и HDInsight. Существует довольно много более изощренных средств, поддерживающих и расширяющих HDInsight, и есть много других проектов с открытым исходным кодом, которые вы можете изучить на портале Apache Hadoop (hadoop.apache.org). Следующим вашим шагом должен стать просмотр видеоролика «Make Your Apps Smarter with Azure HDInsight» на Channel 9 по ссылке bit.ly/19OVzfr. Если вы хотите оставаться конкурентоспособным, принимая решения, обоснованные реальными данными и аналитикой, HDInsight поможет вам в этом.


Бруно Теркали (Bruno Terkaly) — разработчик-идеолог в Microsoft. Его глубокие знания обусловлены долголетним опытом работы в различных областях, написанием кода с использованием множества платформ, языков, инфраструктур, SDK, библиотек и API. Основное внимание в своей работе он уделяет написанию кода, ведению блога и проведению презентаций по созданию облачных приложений, в частности на платформе Microsoft Azure. Читайте его блог blogs.msdn.com/b/brunoterkaly.

Рикардо Виллалобос (Ricardo Villalobos) — квалифицированный архитектор ПО более чем с 15-летним опытом проектирования и создания приложений для компаний в сфере управления цепочками поставок. Читайте его блог blog.ricardovillalobos.com.

Теркали и Виллалобос вместе выступают на крупных отраслевых конференциях. Вы можете связаться с ними по адресу bterkaly@microsoft.com или Ricardo.Villalobos@microsoft.com.

Выражаем благодарность за рецензирование статьи экспертам Пако Натану (Paco Nathan) из Concurrent Inc. и Мэтту Уинклеру (Matt Winkler) из Microsoft.