У mapreduce кожне завдання зменшення запишіть його вихідні дані у файл з іменем part-r-nnnnn, де nnnnn - це ідентифікатор розділу, пов'язаний із завданням зменшення. Чи співпадає / зменшує об’єднання цих файлів? Якщо так, то як?
Відповіді:
Замість того, щоб виконувати злиття файлів самостійно, ви можете делегувати все злиття вихідних файлів зменшення, викликавши:
hadoop fs -getmerge /output/dir/on/hdfs/ /desired/local/output/file.txt
Примітка. Це поєднує файли HDFS локально. Перед запуском переконайтеся, що у вас достатньо місця на диску
getMerge
робить просту конкатенацію файлів, яка з чимось на зразок SequenceFile не дасть розумного виводу.
Ні, Hadoop не об’єднує ці файли. Кількість отриманих файлів однакова з кількістю завдань скорочення.
Якщо вам це потрібно як вхід для наступного завдання, тоді не турбуйтеся про наявність окремих файлів. Просто вкажіть весь каталог як вхідні дані для наступного завдання.
Якщо вам потрібні дані за межами кластера, я зазвичай зливаю їх у приймальному кінці, витягуючи дані з кластера.
Тобто приблизно так:
hadoop fs -cat /some/where/on/hdfs/job-output/part-r-* > TheCombinedResultOfTheJob.txt
Це функція, яку ви можете використовувати для об’єднання файлів у HDFS
public boolean getMergeInHdfs(String src, String dest) throws IllegalArgumentException, IOException {
FileSystem fs = FileSystem.get(config);
Path srcPath = new Path(src);
Path dstPath = new Path(dest);
// Check if the path already exists
if (!(fs.exists(srcPath))) {
logger.info("Path " + src + " does not exists!");
return false;
}
if (!(fs.exists(dstPath))) {
logger.info("Path " + dest + " does not exists!");
return false;
}
return FileUtil.copyMerge(fs, srcPath, fs, dstPath, false, config, null);
}
Лише для текстових файлів та HDFS як джерела та місця призначення використовуйте наведену нижче команду:
hadoop fs -cat /input_hdfs_dir/* | hadoop fs -put - /output_hdfs_file
Це об'єднає всі файли в input_hdfs_dir
і запише вихідні дані назад у HDFS за адресою output_hdfs_file
. Майте на увазі, що всі дані будуть повернуті до локальної системи, а потім знову завантажені в hdfs, хоча тимчасові файли не створюються, і це відбувається на льоту за допомогою UNIX pe.
Крім того, це не буде працювати з нетекстовими файлами, такими як Avro, ORC тощо.
Для двійкових файлів ви можете зробити щось подібне (якщо у вас таблиці Hive зіставлені в каталогах):
insert overwrite table tbl select * from tbl
Залежно від вашої конфігурації, це також може створити більше, ніж файли. Щоб створити один файл, або встановіть явно кількість редукторів до 1, використовуючи, mapreduce.job.reduces=1
або встановіть властивість вулика як hive.merge.mapredfiles=true
.
Файли part-r-nnnnn генеруються після фази зменшення, позначеної між ними r. Тепер факт: якщо у вас запущений один редуктор, ви отримаєте вихідний файл, такий як part-r-00000. Якщо кількість редукторів дорівнює 2, тоді у вас буде частина-r-00000 та частина-r-00001 тощо. Подивіться, якщо вихідний файл занадто великий, щоб поміститися в пам'ять машини, оскільки фреймворк hadoop розроблений для роботи на товарних машинах , тоді файл розколюється. Відповідно до MRv1, у вас є обмеження на 20 редукторів, які працюють за вашою логікою. Можливо, у вас є більше, але те саме потрібно налаштувати у файлах конфігурації mapred-site.xml . Розмова про ваше запитання; Ви можете скористатися getmerge або встановити кількість редукторів до 1, вбудувавши наступний вираз у код драйвера
job.setNumReduceTasks(1);
Сподіваюся, це відповідає на ваше запитання.
Окрім моєї попередньої відповіді, у мене є ще одна відповідь для вас, яку я намагався кілька хвилин тому. Ви можете використовувати CustomOutputFormat, який виглядає як код, наведений нижче
public class VictorOutputFormat extends FileOutputFormat<StudentKey,PassValue> {
@Override
public RecordWriter<StudentKey,PassValue> getRecordWriter(
TaskAttemptContext tac) throws IOException, InterruptedException {
//step 1: GET THE CURRENT PATH
Path currPath=FileOutputFormat.getOutputPath(tac);
//Create the full path
Path fullPath=new Path(currPath,"Aniruddha.txt");
//create the file in the file system
FileSystem fs=currPath.getFileSystem(tac.getConfiguration());
FSDataOutputStream fileOut=fs.create(fullPath,tac);
return new VictorRecordWriter(fileOut);
}
}
Просто погляньте на четвертий рядок з останнього. Я використав своє власне ім'я як ім'я вихідного файлу і протестував програму з 15 редукторами. Файл все ще залишається незмінним. Отже, отримання одного файлу замість двох або більше можливо, але ще бути дуже чітким. Розмір вихідного файлу не повинен перевищувати розмір первинної пам'яті, тобто вихідний файл повинен поміщатися в пам'ять товарної машини, інакше там може бути проблема з розділенням вихідного файлу. Дякую!!
. Чи співпадає / зменшує об’єднання цих файлів?
Ні. Це не зливається.
Ви можете використовувати IdentityReducer для досягнення своєї мети.
Не виконує зменшення, записуючи всі вхідні значення безпосередньо на вихід.
public void reduce(K key,
Iterator<V> values,
OutputCollector<K,V> output,
Reporter reporter)
throws IOException
Записує всі ключі та значення безпосередньо на вихід.
Погляньте на відповідні публікації SE:
hadoop: різниця між редуктором 0 та редуктором ідентичності?