Гнездо GNU Parallel для обработки нескольких огромных файлов и разделения каждого файла данных для обработки в виде очереди

У меня есть каталог с почти 100 файлами журналов, каждый весом 10 ~ 15 ГБ. Требуется прочитать построчно каждый файл (порядок не имеет значения), очистить строку json и выгрузить ее в хранилище эластичного поиска бэкэнда для индексации.

вот мой работник, который делает эту работу

# file = worker.php

echo " -- New PHP Worker Started -- "; // to get how many times gnu-parallel initiated the worker
$dataSet = [];

while (false !== ($line = fgets(STDIN))) {

// convert line text to json
$l = json_decode($line);
$dataSet[] = $l;

if(sizeof($dataSet) >= 1000) {
//index json to elasticsearch
$elasticsearch->bulkIndex($dataSet);
$dataSet = [];
}
}

С помощью ответов Вот а также Вот Я почти там, и он работает (вроде), но мне просто нужно убедиться, что под капотом он действительно делает то, что, как я предполагаю, он делает.

С одним файлом я могу справиться, как показано ниже

parallel --pipepart -a 10GB_input_file.txt  --round-robin php worker.php

Это прекрасно работает. добавление —round-robin гарантирует, что рабочий процесс php запускается только один раз, а затем просто продолжает получать данные в виде конвейера (очередь бедного человека).

Таким образом, для машины 4CPU она запускает 4 php работников и очень быстро обрабатывает все данные.

Чтобы сделать то же самое для всех файлов, вот мой взгляд на это

find /data/directory -maxdepth 1 -type f | parallel cat | parallel --pipe -N10000 --round-robin php worker.php

Что-то вроде работает, но у меня есть ощущение, что это неправильный способ вложения параллели для всех файлов.

А во-вторых, поскольку он не может использовать —pipepart, я думаю, что это медленнее.

В-третьих, как только работа завершена, я вижу, что на 4-процессорной машине только 4 рабочих были запущены, и работа была выполнена. Это правильное поведение? Разве это не должно запускать 4 рабочих для каждого файла? Просто хочу убедиться, что я не пропустил никаких данных.

Есть идеи, как это можно сделать лучше?

1

Решение

Если они примерно одинакового размера, почему бы просто не дать один файл каждому:

find /data/directory -maxdepth 1 -type f |
parallel php worker.php '<' {}

Другой способ заключается в использовании --pipepart на каждом из них:

do_one() {
parallel --pipepart -a "$1" --block -1 php worker.php
}
export -f do_one
find /data/directory -maxdepth 1 -type f | parallel -j1 do_one

Если это не займет много времени, чтобы начать php worker.php тогда последний может быть предпочтительнее, потому что он будет распределяться более равномерно, если файлы очень разных размеров, поэтому, если последний файл огромен, вам не придется ждать, пока один процесс завершит его обработку.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]