Несколько выходов в hadoop

Я использую MultipleOutputs в моей программе сокращения моей фазы сокращения. Набор данных, над которым я работаю, составляет около 270 МБ, и я запускаю его на своем псевдораспределенном одном узле. Я использовал пользовательские записи для выходных значений моей карты. ключи - это страны, представленные в наборах данных.

public class reduce_class extends Reducer<Text, name, NullWritable, Text> {
    public void reduce(Text key,Iterable<name> values,Context context) throws IOException, InterruptedException{
        MultipleOutputs<NullWritable,Text> m = new MultipleOutputs<NullWritable,Text>(context);
        long pat;
        String n;
        NullWritable out = NullWritable.get();
        TreeMap<Long,ArrayList<String>> map = new TreeMap<Long,ArrayList<String>>();
        for(name nn : values){
            pat = nn.patent_No.get();
            if(map.containsKey(pat))
                map.get(pat).add(nn.getName().toString());
            else{
                map.put(pat,(new ArrayList<String>()));
                map.get(pat).add(nn.getName().toString());}
    }
        for(Map.Entry entry : map.entrySet()){
            n = entry.getKey().toString();
            m.write(out, new Text("--------------------------"), key.toString());
            m.write(out, new Text(n), key.toString());
            ArrayList<String> names = (ArrayList)entry.getValue();
            Iterator i = names.iterator();
            while(i.hasNext()){
                n = (String)i.next();
                m.write(out, new Text(n), key.toString());
        }
            m.write(out, new Text("--------------------------"), key.toString());           
    }
        m.close();
}

}

выше моя логика сокращения

проблемы

1) приведенный выше код прекрасно работает с небольшим набором данных, но не работает из-за пространства кучи с набором данных 270 МБ.

2) Использование страны в качестве ключа передает довольно большие значения в одну итеративную коллекцию. Я пытался решить эту проблему, но MutlipleOutputs создает уникальные файлы для данного набора ключей. Дело в том, что я не могу добавить уже существующий файл, созданный предыдущим запуском метода Reduce and throws error. таким образом, для определенных ключей я должен создать новые файлы. Есть ли способ обойти это?, Решение вышеуказанной ошибки заставило меня определить ключи как названия стран (мои последние отсортированные данные), но выдает ошибку кучи Java.

Пример ввода

3858241,"Durand","Philip","E.","","","Hudson","MA","US","",1 3858241,"Norris","Lonnie","H.","","","Milford","MA","US","",2 3858242,"Gooding","Elwyn","R.","","120 Darwin Rd.","Pinckney","MI","US","48169",1 3858243,"Pierron","Claude","Raymond","",","Epinal","","FR","",1 3858243,"Дженни", "Джин", "Пол","","","Decines","","FR","",2 3858243,"Zuccaro","Robert","","","","Epinal","","FR","",3 3858244,"Mann","Richard","L.","","PO Box 69","Woodstock","CT","США","06281",1

Пример вывода для небольших наборов данных

пример структуры каталогов...

CA-R-00000

FR-т-00000

Квебек-т-00000

TX-т-00000

США-т-00000

*Индивидуальное содержание*


3858241 Филип Э. Дюран

Лонни Х. Норрис


3858242

Элвин Р. Гудинг


3858244

Ричард Л. Манн


1 ответ

Я знаю, что отвечаю на очень старый вопрос здесь, но в любом случае позвольте мне высказать некоторые идеи здесь. Кажется, вы создаете TreeMap в своем редукторе со всеми записями, которые вы получаете за один вызов сокращения. В Mapreduce вы не можете позволить себе хранить все записи в памяти, потому что они никогда не масштабируются. Вы делаете карту patent_no и все names связано с этим patent_no, Все, что вы хотите, это выделить записи на основе patent_no, так почему бы не использовать сортировку структуры mapreduce.

Вы должны включить patent_no а также name вместе с country в самом доступном для записи ключе.

  • Пиши свой Partitioner разделять только на основе country,
  • Сортировка должна быть включена country, patent_no, name,
  • Вы должны написать свой Grouping comparator группировать по country, patent_no,

В результате все записи с одинаковыми country будет идти к тому же редуктору и отсортированы по patent_no а также name, И в пределах одного и того же редуктора разные патентные номера будут отправляться на разные вызовы сокращения. Теперь все, что вам нужно, это просто написать это в MultipleOutputs. Таким образом вы избавитесь от любого в памяти TreeMap.

И некоторые моменты, о которых я бы посоветовал вам позаботиться:

  • Не создавать new MultipleOutputs в методе Reduce каждый раз вместо этого вы должны написать setup() метод и создать только один в setup() метод.
  • Не создавать new Text() каждый раз вместо этого создайте один в методе установки и повторно используйте тот же экземпляр set("string") метод Text, Вы можете утверждать, что в этом смысл, GC Java все равно будет собирать мусор. Но вы всегда должны стараться использовать как можно меньше памяти, чтобы сборщик мусора Java вызывался реже.
Другие вопросы по тегам