копирование в и из hdfs в потоковой передаче Hadoop

#java #hadoop #hadoop-streaming

#java #hadoop #потоковая передача hadoop

Вопрос:

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

Проблема

Предположим, вы пытаетесь написать потоковое задание Hadoop, которое загружает кучу действительно больших файлов в hdfs. Руководство по потоковой передаче Hadoop предлагает вам написать mapper для копирования файла из hdfs на локальный узел, выполнить свою работу, а затем скопировать файл обратно в hdfs. Вот небольшой скрипт с некоторым дополнительным кодом, который объясняется встроенным, для выполнения немного более простой задачи: просто переименуйте некоторый файл

Сценарий

 #!/bin/bash

# Remove "s from the environment variable to work around a stupid bug in hadoop.
export HADOOP_CLIENT_OPTS=`echo $HADOOP_CLIENT_OPTS | tr -d '"'`

# Get just the size of the file on the local disk.
function localSize() {
 ls -l $1 | awk '{ print $5 }'
}

# Get just the size of the file on HDFS.  Oddly, the first command includes a 
# new line at the start of the size, so we remove it by using a substring.
function hdfsSize() {
 s=`hadoop dfs -ls /some/other/path/$1 | awk '{ print $5 }'`
 echo ${s:1}
}

while read line
do
 ds=ourFile.dat
 # Copy the file from HDFS to local disk.
 hadoop dfs -copyToLocal /path/to/some/large/file/$ds $ds
 # Spin until the file is fully copied.
 while [ ! -f $ds ]
 do 
  echo "spin"
  sleep 1 
 done

 # Delete the renamed version of the file and copy it.
 hadoop dfs -rm /some/other/path/blah
 hadoop dfs -copyFromLocal $ds /some/other/path/blah
 # Print out the sizes of the file on local disk and hdfs, they *should* be equal
 localSize $ds
 hdfsSize blah
 # If they aren't equal, spin until they are.
 while [ "`localSize $ds`" != "`hdfsSize blah`" ]
 do
  echo "copy spin"
  sleep 1
 done
 # Print out the file size at the end, just for fun.
 hadoop dfs -ls /some/other/path/blah
done
  

Вывод

После запуска скрипта мы получаем следующий вывод

 spin
spin
spin
Deleted hdfs://kracken:54310/some/other/path/blah
200890778
67108864
copy spin
Found 1 items   
-rw-r--r--   3 hadoop supergroup  200890778 2011-10-06 16:00 /home/stevens35/blah
  

Проблема

Кажется очевидным, что hadoop dfs -copyToLocal and hadoop dfs -copyFromLocal , похоже, возвращается до завершения передачи соответствующих файлов, как видно spin copy spin из выходных данных and . Я предполагаю, что потоковая jvm Hadoop использует поток, созданный hadoop dfs командой, и поэтому потоки передачи файлов продолжают выполняться, даже несмотря hadoop dfs на выход, но это всего лишь предположение. Это становится особенно раздражающим, когда файл большой, и потоковая передача Hadoop завершается до завершения копирования последнего файла; кажется, что передача файла прерывается на полпути, и вы остаетесь с исходным файлом в HDFS. Этот мой взлом, по крайней мере, гарантирует, что копирование файлов завершится.

Я должен отметить, что я использую версию hadoop от Cloudera 0.20.2 737.

Кто-нибудь сталкивался с этой проблемой? Какие альтернативные обходные пути вы нашли? И была ли проблема исправлена в каких-либо новых версиях Hadoop?

Комментарии:

1. Я видел аналогичный запрос в stackoverflow для неполного файла с использованием copyToLocal в потоковой передаче, но не смог его найти. Похоже, это ошибка в Hadoop. Задайте тот же вопрос в mapreduce-dev@hadoop.apache.org и подайте JIRA, если требуется. Я видел код , и copyToLocal, похоже, является только синхронным вызовом. Кроме того, OutputStream.flush() явно не вызывается, не уверен, что flush() вызывается автоматически в close() . Сообщите нам решение.

2. Этот аналогичный запрос был моим, но я удалил его, чтобы я мог написать этот более подробно, не имея повторяющегося запроса 🙂 Я планирую подать заявку, но я хотел оставить это здесь частично, чтобы другие люди здесь знали о проблеме и видели обходной путь, и чтобы посмотреть, пробовали ли другие здесь что-нибудь.

3. Я не видел большой активности / глаз вокруг Hadoop здесь, в SO, поэтому лучше отправить его в mapreduce-dev и подать JIRA, если это действительно ошибка.

4. Реализация copyToLocal выглядит полностью синхронной. Может быть, это проблемы с кэшированием локальной файловой системы? Какая у вас ОС, локальная fs?