Я задавал подобный вопрос к этому ранее, но после некоторого изучения у меня есть лучшее понимание того, что происходит, но я хотел бы видеть, есть ли у других людей альтернативные решения для моего подхода.
Проблема
Предположим, вы пытаетесь написать потоковое задание Hadoop, которое собирает файлы очень больших файлов в формате hdf. Руководство по потоковой передаче Hadoop предлагает вам написать картограф для копирования файла из hdf на локальный узел, выполнить свою работу, а затем скопировать файл обратно в 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
и hadoop dfs -copyFromLocal
, кажется, возвращаются до того, как соответствующие файлы закончили передачу, как видно извыходы spin
и copy spin
.Я предполагаю, что потоковый jvm Hadoop принимает поток, созданный командой hadoop dfs
, и поэтому потоки передачи файлов продолжают работать даже после выхода hadoop dfs
, но это всего лишь предположение.Это становится особенно раздражающим, когда файл большой, и потоковая передача Hadoop завершается до того, как последний файл завершит копирование;кажется, что передача файлов заканчивается на полпути, и у вас остаётся файл paritial в HDFS.Похоже, этот мой хак, по крайней мере, гарантирует, что файлы заканчивают копировать.
Должен заметить, что я использую версию 0.20.2 + 737 Cloudera.
Кто-нибудь сталкивался с этой проблемой?Какую альтернативную работу вы нашли?И была ли эта проблема исправлена в новых выпусках Hadoop?