hadoop_with_php_post_logo

Сегодня посчастливилось ознакомиться со статьей Майкла Нолла (Michael Noll) о том, как написать распределённое Hadoop приложение на питоне (Python). Я всегда был большим поклонником распределённой обработки (MapReduce), но, так как в своей работе использую PHP, я подумал, что неплохо бы было портировать этот пример и показать, как можно создавать распределенные приложения на PHP.

Чтобы глубже понять, что мы будем делать дальше, рекомендую прочитать упомянутую выше оригинальную статью. Для начала нужно установить и запустить Hadoop, но установка Hadoop-кастера — это довольно нетривиальная задача, с которой можно провозиться весь день. Однако, если Вы хотите поэкспериментировать с платформой прямо сейчас, можно загрузить образ виртуальной машины с предварительно сконфигурированной единичной Hadoop нодой. Конечно, у Вас не будет высокопроизводительного Hadoop-кластера, но будет возможность проводить эксперименты на своей локальной машине, запуская простые MapReduce задачи. Виртуалка создана так, что её можно использовать с помощью бесплатного VMware плеера.

Образ виртуальной машины можно загрузить с Google Code University (150Мб). Образ имеет предустановленных пользователей:

root root

guest guest

Для установки php5 запустите

apt-get install php5-cli

из-под пользователя root. Если не устанавливается, сделайте

apt-get update

и повторите установку php.

Маp: mapper.php

Скрипт, который выполняет кусочек основной задачи. Сохраните приведенный ниже код в файл /home/guest/mapper.php:

#!/usr/bin/php
<?php
$word2count = array();
// Ввод данных происходит через STDIN
while (($line = fgets(STDIN)) !== false) {
   // убираем лишние символы и переводим в нижний регистр
   $line = strtolower(trim($line));
   // разбиваем строки по словам и убираем пустые значения
   $words = preg_split('/\W/', $line, 0, PREG_SPLIT_NO_EMPTY);
   // увеличиваем счетчик
   foreach ($words as $word) {
       $word2count[$word] += 1;
   }
}

// Вывод результатов в STDOUT
// Эти данные будут обрабатываться "склеиваться" reducer.php
// Reduce step, i.e. the input for reducer.py
foreach ($word2count as $word => $count) {
   // разделение табуляцией
   echo $word, chr(9), $count, PHP_EOL;
}
?>

Reduce: reducer.php

Сохраните приведенный ниже код в файл /home/guest/reducer.php:

#!/usr/bin/php
<?php
$word2count = array();
// input comes from STDIN
while (($line = fgets(STDIN)) !== false) {
    // убираем лишние символы и переводим в нижний регистр
    $line = trim($line);
    // разбираем данные, которые прислал mapper.php
    list($word, $count) = explode(chr(9), $line);
    // приводим тип - из строки в целое число
    $count = intval($count);
    // суммируем
    if ($count > 0) $word2count[$word] += $count;
}

// сортируем результат
//
// это не обязательно, но есть в официальном примере работы с Hadoop
ksort($word2count);
// выводим результат в STDOUT
foreach ($word2count as $word => $count) {
    echo $word, chr(9), $count, PHP_EOL;
}
?>

Не забудьте выставить права на выполнение скрипта.

chmod +x /home/guest/mapper.php /home/guest/reducer.php

Запускаем PHP-код на Hadoop:

Загружаем тестовые данные

Как и у Майкла Нолла, для данного примера мною были использованы электронные книги из проекта Gutenberg :

Загрузите каждую книгу и сохраните ее в какую-нибудь директорию на выбор, например в /tmp/gutenberg 

Копируем данные на распределённую файловую систему HDFS

Перед запуском тестовой задачи нужно скопировать данные с локальной файловой системы на распределённую файловую систему Hadoop’s HDFS

bin/hadoop dfs -copyFromLocal /tmp/gutenberg gutenberg

Запускаем тестовый пример

Теперь все готово к запуску нашей распределенной задачи на Hadoop-кластере. Для того, чтобы уменьшить обмен данными через STDIN и STDOUT между Map и Reduce компонентами, используем HadoopStreaming.

bin/hadoop jar contrib/hadoop-streaming.jar 
-mapper /home/guest/mapper.php 
-reducer /home/guest/reducer.php 
-input gutenberg/* -output gutenberg-output

Как это работает

Эта задача читает все файлы в HDFS директории gutenberg, обрабатывает их и сохраняет результат в файл, который находится в HDFS директории gutenberg-output.

Вы можете проследить состояние задачи, используя web-интерфейс Hadoop: http://localhost:50030/

Hadoop-web-interface-screenshot

Когда задача будет отработана, проверьте, чтобы результат был сохранен в выходной HADOOP директории gutenberg-output:

bin/hadoop dfs -ls gutenberg-output

Вы также можете просмотреть содержимое файла, используя команду dfs -cat:

bin/hadoop dfs -cat gutenberg-output/part-00000

Вот и все, познавайте магию Hadoop — это будущее 😉

Оригинальная статья: от Robin Schuil

Оригинал этой статьи

Комментарии

comments powered by Disqus