Недавно на работе мне нужно было просмотреть наши архивные файлы и предоставить результаты к концу дня. Вот параметры запроса:
- Архивные файлы зашифрованы и хранятся в HDFS (не спрашивайте, почему мы храним их в HDFS).
- Файлы различаются по размеру от 3 до 9 ГБ.
- Общее количество файлов для поиска было 300+
- Расшифровка каждого файла занимает от 1 до 2 минут.
В прошлом были запросы на поиск в одном архивном файле. В этих случаях мы будем копировать файл из HDFS на сервер. Затем запустите сценарий оболочки, чтобы расшифровать файл и выполнить поиск. Программа расшифровки требует 2 аргумента: зашифрованный файл и файл для записи расшифрованных данных. Это означает, что расшифрованный и зашифрованный файл находятся на диске одновременно.
При средней скорости 1,5 минуты для расшифровки одного файла для 300 файлов требовалось 450 минут (7,5 часов). Чтобы добавить к моей дилемме, не было достаточно времени, чтобы написать собственный RecordReader . Единственным решением было бы передавать файлы параллельно. Но есть 2 проблемы с этим подходом:
- На сервере недостаточно места для 20 (10 зашифрованных и 10 расшифрованных) файлов одновременно.
- Код дешифрования выполняет чтение из стандартного ввода или запись в стандартный вывод.
Что делать? Используйте именованные каналы, конечно!
Ускоренный курс по именованным каналам
Трубы используются для составления узконаправленных программ для решения более широких задач. Например :
cat someFile.txt | awk -F "|" '{print $5}' | cut -d ':' f2
В этом примере мы используем анонимные каналы (обозначаемые символом «|»). Трубы, используемые в командной строке или в сценариях, живут только в течение текущего процесса. Именованные каналы похожи с этими исключениями:
- Вы создаете именованные каналы с помощью команды
mkfifo name-of-pipe
. - Может использоваться повторно несколькими процессами.
- Namped трубы сохраняются, пока не будут удалены с помощью команды
rm name-of-pipe
. - Существуют в файловой системе и отображаются в виде файлов для других процессов.
- Разрешить межпроцессное взаимодействие.
Вот пример создания именованного канала и как он выглядит в файловой системе:
new-host-2:~ bbejeck$ mkfifo pipe1 new-host-2:~ bbejeck$ ls -l pipe1 prw-r--r-- 1 bbejeck staff 0 Aug 16 21:28 pipe1
Обратите внимание, что именованный канал отображается в ls
результатах, и первый столбец слева — это p
. Если вам больше не нужен именованный канал, просто удалите его, как файл с командой rm pipe1
.
Мое решение с именованными трубами
Сначала я создал файл, состоящий из путей к архивам. Затем скрипт перебрал файл и запустил 10 процессов дешифрования / поиска параллельно. После запуска 10 процессов сценарий будет ожидать завершения всех 10 процессов, прежде чем запускать другой пакет.
count=0 while read fileName; do if [[ $((++count)) -eq 10 ]]; then count = 0 wait fi #backgrounded process processFile $fileName & done < inputFileNames.txt
Вот код для processFile
функции.
function processFile { encryptedFile=$(basename ${1}) decryptedFile=${encryptedFile%.enc} mkfifo ${encryptedFile} mkfifo ${decryptedFile} hdfs dfs -cat ${1} > ${encryptedFile} & cat ${decryptedFile} | awk '{ if ( $5 == someValue) print $0}' & /somepath/decryptFile.sh ${encryptedFile} ${decryptedFile} rm ${encryptedFile} ${decryptedFile} }
Хотя processFile
функция проста, есть несколько шагов, которые мы должны объяснить:
- Строка 2: создайте переменную с базовым именем зашифрованного файла из полного пути.
- Строка 3: создайте переменную имени зашифрованного файла за вычетом
.enc
расширения файла. - Строки 5,6: Создание именованных каналов для зашифрованного и расшифрованного файла.
- Строка 8: поток зашифрованный файл из HDFS и перенаправить на зашифрованный именованный канал и фоновый процесс.
- Строка 9: Запустите
cat
команду для расшифрованного файла. Затем передайте результатыawk
и найдите нужную информацию. Это тоже фоновое. - Строка 11: вызов сценария дешифрования с необходимыми параметрами файла.
- Строка 12: после расшифровки и поиска файла удалите именованные каналы.
Вывод
Использование именованных каналов позволило мне расшифровать и найти более 300 файлов примерно за 1,5 часа. Я также избежал проблемы с пространством, так как мне никогда не приходилось записывать файл на диск. Хотя именованные каналы не нужны каждый день, они являются полезным инструментом в вашем арсенале.