перемещение большого количества файлов из hdfs в hdfs

Мне нужно переместить (не скопировать) много файлов из одного каталога hdfs в другой каталог hdfs в том же кластере.

Я мог бы использовать distcp, но это кажется излишним, поскольку он копирует файл (дублирует его). Я просто хочу его переместить. Два вопроса:

А) Есть ли там что-нибудь:

Я хотел бы использовать mapreduce для этого, так как есть миллионы файлов, которые нужно переместить (или переименовать на новый путь). Я также хочу интегрировать его с oozie. Я мог бы сам написать работу по уменьшению карты, но мне было интересно, есть ли что-то, что могло бы выполнить эту работу.

Б) Мне действительно нужно делать это как mapred?

К сожалению, я недостаточно знаю о характеристиках производительности переименования hdfs; как вы думаете, я мог бы найти способ с однопоточным подходом к переименованию файлов?


person hba    schedule 07.01.2014    source источник


Ответы (2)


Само перемещение является эффективным, поскольку оно выполняется только на уровне метаданных (т. е. inode), а не на уровне данных. Другими словами, выполнение перемещения (которое внутри кода Hadoop называется rename, а не move) выполняется намного быстрее, чем копирование данных. Вы можете взглянуть на исходный код, если вас интересуют подробности.

По этой причине вам не следует выполнять distcp, так как это будет реальная копия данных. Если вы хотите распараллелить его (поскольку вы говорите о миллионах файлов), это не должно быть слишком сложно с использованием потоковой передачи Hadoop:

  1. Напишите несколько файлов, содержащих список файлов для переименования (источник + пункт назначения), по одному в строке.
  2. Напишите сценарий оболочки, чтобы выполнить переименование (команда hdfs mv) для каждой строки, которую он читает на стандартном вводе.
  3. Используйте потоковую передачу: ваши файлы с файлами являются входными данными, ваш сценарий оболочки является картографом.

Там что-нибудь есть?

Я не в курсе, но может быть.

Мне действительно нужно сделать это как mapred?

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

person cabad    schedule 07.01.2014

Я придумал это, если вы хотите скопировать подмножество файлов из папки в другую в HDFS:

import pandas as pd
import os
from multiprocessing import Process
from subprocess import Popen, PIPE
hdfs_path_1 = '/path/to/the/origin/'
hdfs_path_2 = '/path/to/the/destination/'

df = pd.read_csv("list_of_files.csv")  
to_do_list = list(df.tar) # or any other lists that you have
print(f'To go: {len(to_do_list)}')

def copyy(f):
    process = Popen(f'hdfs dfs -mv {hdfs_path_1}{f} {hdfs_path_2}', shell=True, stdout=PIPE, stderr=PIPE)
    std_out, std_err = process.communicate()
    if std_out!= b'':
        print(std_out)

ps = []
for f in to_do_list:
    p = Process(target=copyy, args=(f,))
    p.start()
    ps.append(p)
for p in ps:
    p.join()
print('done')

Также, если вы хотите иметь список всех файлов в каталоге, используйте это:

from subprocess import Popen, PIPE
hdfs_path = '/path/to/the/designated/folder'
process = Popen(f'hdfs dfs -ls -h {hdfs_path}', shell=True, stdout=PIPE, stderr=PIPE)
std_out, std_err = process.communicate()
list_of_file_names = [fn.split(' ')[-1].split('/')[-1] for fn in std_out.decode().readlines()[1:]][:-1]
list_of_file_names_with_full_address = [fn.split(' ')[-1] for fn in std_out.decode().readlines()[1:]][:-1]
person Ehsan Fathi    schedule 31.03.2020