Малките файлове са голям проблем в Hadoop – или поне са, ако броят на въпросите в списъка с потребители по тази тема е нещо, което трябва да преминете. В тази публикация ще разгледам проблема и ще разгледам някои често срещани решения.
Проблеми с малки файлове и HDFS
Малък файл е този, който е значително по-малък от размера на HDFS блока (по подразбиране 64MB). Ако съхранявате малки файлове, тогава вероятно имате много от тях (в противен случай не бихте се обърнали към Hadoop), а проблемът е, че HDFS не може да обработва много файлове.
Всеки файл, директория и блок в HDFS се представя като обект в паметта на възела на име, всеки от които заема 150 байта, като правило. Така 10 милиона файла, всеки от които използва блок, ще използват около 3 гигабайта памет. Увеличаването много отвъд това ниво е проблем с текущия хардуер. Със сигурност един милиард файлове не е възможно.
Освен това HDFS не е насочен към ефективен достъп до малки файлове:той е предназначен предимно за поточно достъп до големи файлове. Четенето на малки файлове обикновено причинява много търсения и много прескачане от datanode на datanode за извличане на всеки малък файл, като всичко това е неефективен модел за достъп до данни.
Проблеми с малки файлове и MapReduce
Задачите за картографиране обикновено обработват блок от въвеждане наведнъж (използвайки FileInputFormat
по подразбиране ). Ако файлът е много малък и има много от тях, тогава всяка задача за карта обработва много малко входни данни и има много повече задачи за карти, всяка от които налага допълнителни счетоводни разходи. Сравнете файл от 1 GB, разделен на 16 блока от 64 MB, и 10 000 или около 100 KB файла. 10 000 файла използват по една карта всеки и времето за работа може да бъде десетки или стотици пъти по-бавно от еквивалентното с един входен файл.
Има няколко функции, които помагат за облекчаване на счетоводните разходи:JVM задачата се използва повторно за изпълнение на множество задачи за карти в една JVM, като по този начин се избягват някои допълнителни разходи при стартиране на JVM (вижте mapred.job.reuse.jvm.num.tasksкод> свойство) и
MultiFileInputSplit
който може да изпълнява повече от един сплит на карта.
Защо се създават малки файлове?
Има поне два случая
- Файловете са части от по-голям логически файл. Тъй като HDFS едва наскоро поддържа приложения, много често срещан модел за запазване на неограничени файлове (напр. регистрационни файлове) е записването им на парчета в HDFS.
- Файловете по своята същност са малки. Представете си голям корпус от изображения. Всяко изображение е отделен файл и няма естествен начин да ги комбинирате в един по-голям файл.
Тези два случая изискват различни решения. За първия случай, когато файлът е съставен от записи, проблемът може да бъде избегнат чрез извикване на sync()
на HDFS метод много често за непрекъснато писане на големи файлове. Като алтернатива е възможно да се напише програма за свързване на малките файлове заедно.
За втория случай е необходим някакъв контейнер за групиране на файловете по някакъв начин. Hadoop предлага няколко опции тук.
HAR файлове
Hadoop Archives (HAR файлове) бяха въведени в HDFS в 0.18.0, за да облекчат проблема с много файлове, оказващи натиск върху паметта на namenode. HAR файловете работят чрез изграждане на многопластова файлова система върху HDFS. HAR файл се създава с помощта на hadoop архив
команда, която изпълнява задача MapReduce за пакетиране на архивираните файлове в малък брой HDFS файлове. За клиент, използващ файловата система HAR, нищо не се е променило:всички оригинални файлове са видими и достъпни (макар и с помощта на har:// URL). Въпреки това, броят на файловете в HDFS е намален.
Четенето на файлове в HAR не е по-ефективно от четенето на файлове в HDFS и всъщност може да бъде по-бавно, тъй като всеки достъп до HAR файл изисква две четения на индексни файлове, както и четене на файла с данни (вижте диаграмата). И въпреки че HAR файловете могат да се използват като вход за MapReduce, няма специална магия, която позволява на картите да работят върху всички файлове в HAR, който е сърезидент на HDFS блок. Би трябвало да е възможно да се изгради входен формат, който да се възползва от подобреното местоположение на файловете в HAR, но той все още не съществува. Имайте предвид, че MultiFileInputSplit, дори с подобренията в HADOOP-4565 за избор на файлове в разделяне, които са локални на възел, ще се нуждае от търсене за малък файл. Би било интересно да се види ефективността на това в сравнение с SequenceFile, да речем. В момента HAR вероятно е най-добре да се използват само за архивни цели.
Файлове на последователност
Обичайният отговор на въпроси относно „проблема с малките файлове“ е:използвайте SequenceFile. Идеята тук е, че използвате името на файла като ключ и съдържанието на файла като стойност. Това работи много добре на практика. Връщайки се към 10 000 100KB файлове, можете да напишете програма, която да ги постави в един SequenceFile и след това можете да ги обработвате по стрийминг начин (директно или с помощта на MapReduce), работещ върху SequenceFile. Има и няколко бонуса. SequenceFiles са разделяеми, така че MapReduce може да ги разбие на парчета и да работи с всяка част независимо. Те също така поддържат компресия, за разлика от HAR. Блоковата компресия е най-добрият вариант в повечето случаи, тъй като компресира блокове от няколко записа (а не на запис).
Преобразуването на съществуващи данни в SequenceFiles може да бъде бавно. Въпреки това е напълно възможно да създадете паралелно колекция от SequenceFiles. (Стюарт Сиера написа много полезна публикация за конвертирането на tar файл в SequenceFile — инструменти като този са много полезни и би било добре да видите повече от тях). В бъдеще е най-добре да проектирате тръбопровода си за данни така, че да записвате данните в източника директно в SequenceFile, ако е възможно, вместо да пишете в малки файлове като междинна стъпка.
За разлика от HAR файловете, няма начин да се изброят всички ключове в SequenceFile, освен четене на целия файл. (MapFiles, които са като SequenceFiles със сортирани ключове, поддържат частичен индекс, така че те също не могат да изброят всичките си ключове – вижте диаграмата.)
SequenceFile е по-скоро ориентиран към Java. TFile е проектиран да бъде междуплатформен и да бъде заместител на SequenceFile, но все още не е наличен.
HBase
Ако създавате много малки файлове, тогава, в зависимост от модела на достъп, различен тип съхранение може да е по-подходящ. HBase съхранява данни в MapFiles (индексирани SequenceFiles) и е добър избор, ако трябва да правите поточно анализи в стил MapReduce с от време на време произволно търсене. Ако забавянето е проблем, тогава има много други възможности за избор – вижте отличното проучване на Ричард Джоунс за магазините ключ-стойност.