Hadoop - соответствующий размер блока для нерасщепляемых файлов разного размера (200-500 мб)

Если мне нужно выполнить последовательное сканирование (нерасщепляемых) тысяч gzip файлов размером от 200 до 500 МБ, что такое размер блока для этих файлов?

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

Мое понимание:

  • Вряд ли есть верхний предел размера блока, так как там "много файлов" для соответствующего количества картографов для размера моего кластера.
  • Чтобы обеспечить локальность данных, я хочу, чтобы каждый файл gzip находился в 1 блоке.

Однако файлы gzipped имеют разные размеры. Как хранятся данные, если я выбираю размер блока ~ 500 мб (например, максимальный размер файла для всех моих входных файлов)? Было бы лучше выбрать "очень большой" размер блока, например 2 ГБ? Является ли емкость жесткого диска чрезмерно избыточной в любом сценарии?

Наверное, я действительно спрашиваю, как файлы хранятся и разделяются по блокам hdfs, а также пытается понять оптимальную практику для нерасщепляемых файлов.

Обновление: конкретный пример

Скажем, что я запускаю MR Job на трех 200 МБ файлах, как показано на следующем рисунке.

Если HDFS хранит файлы, как в случае A, гарантировано, что 3 модуля будут обрабатывать "локальный" файл каждый. Однако, если файлы хранятся, как в случае B, одному картографу потребуется извлечь часть файла 2 из других данных node.

Учитывая наличие большого количества свободных блоков, файлы HDFS хранят, как показано в случае A или case B?

HDFS strategies

Ответ 1

Если у вас есть файлы без расщепления, вам лучше использовать большие размеры блоков - размером с сами файлы (или больше, это не имеет значения).

Если размер блока меньше, чем общий размер файла, тогда вы сталкиваетесь с тем, что все блоки не все находятся на одних и тех же данных node, и вы теряете локальность данных. Это не проблема с splittable файлами, поскольку задача карты будет создана для каждого блока.

Что касается верхнего предела размера блока, я знаю, что для некоторой более старой версии Hadoop предел составлял 2 ГБ (выше которого содержимое блока было недоступно) - см. https://issues.apache.org/jira/browse/HDFS-96

Нет недостатка в хранении небольших файлов с большими размерами блоков. Чтобы подчеркнуть этот момент, рассмотрите файл размером 1 МБ и 2 ГБ, каждый с размером блока 2 ГБ:

  • 1 МБ - 1 блок, одна запись в имени Node, 1 МБ, физически сохраненная на каждой реплике node
  • 2 ГБ - 1 блок, одна запись в имени Node, 2 ГБ, физически сохраненная на каждой реплике node

Так же, как и для требуемого физического хранилища, нет никакой нисходящей стороны в таблице блоков Name node (оба файла имеют одну запись в таблице блоков).

Единственным возможным недостатком является время, затрачиваемое на репликацию меньшего по сравнению с большим блоком, но с другой стороны, если данные из node теряются из кластера, тогда задача 2000 x 1 МБ блоков для репликации медленнее, чем блок с блоком 2 ГБ.

Обновление - обработанный пример

Увидев, что это вызывает некоторую путаницу, некоторые примеры работы:

Скажем, у нас есть система с размером блока HDFS размером 300 МБ, и для упрощения работы у нас есть кластер psuedo с только одним данным node.

Если вы хотите сохранить файл размером 1100 МБ, то HDFS разложит этот файл на не более 300 МБ блоков и сохранит данные node в файлах с индексированным индексом. Если вы хотите перейти к данным node и посмотреть, где хранятся индексированные файлы блоков на физическом диске, вы можете увидеть что-то вроде этого:

/local/path/to/datanode/storage/0/blk_000000000000001  300 MB
/local/path/to/datanode/storage/0/blk_000000000000002  300 MB
/local/path/to/datanode/storage/0/blk_000000000000003  300 MB
/local/path/to/datanode/storage/0/blk_000000000000004  200 MB

Обратите внимание, что файл не точно делится на 300 МБ, поэтому последний блок файла имеет размер по модулю файла по размеру блока.

Теперь, если мы повторим одно и то же упражнение с файлом, меньшим размера блока, скажем 1 МБ, и посмотрим, как он будет храниться в данных node:

/local/path/to/datanode/storage/0/blk_000000000000005  1 MB

Снова обратите внимание, что фактический файл, хранящийся в данных node, составляет 1 МБ, НЕ 200 МБ файл с 299 МБ нулевого заполнения (что, по моему мнению, является причиной путаницы).

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

filename     index     datanode
-------------------------------------------
fileA.txt    blk_01    datanode1
fileA.txt    blk_02    datanode1
fileA.txt    blk_03    datanode1
fileA.txt    blk_04    datanode1
-------------------------------------------
fileB.txt    blk_05    datanode1

Вы можете видеть, что если бы вы использовали размер блока 1 МБ для файла file.txt, вам понадобилось бы 1100 записей на приведенной выше карте, а не 4 (для чего потребуется больше памяти в имени node). Кроме того, откат всех блоков будет дороже, поскольку вы делаете 1100 RPC-вызовов для datanode1, а не 4.

Ответ 2

Я попытаюсь выделить в качестве примера различия в разбиениях блоков в отношении размера файла. В HDFS у вас есть:

Splittable FileA size 1GB
dfs.block.size=67108864(~64MB)

Работа MapRed с этим файлом:

16 splits and in turn 16 mappers.

Посмотрите на этот сценарий с помощью сжатого (нерасщепляемого) файла:

Non-Splittable FileA.gzip size 1GB
dfs.block.size=67108864(~64MB)

Работа MapRed с этим файлом:

16 Blocks will converge on 1 mapper.

Лучше всего уклониться от этой ситуации, так как это означает, что tasktracker должен будет извлечь 16 блоков данных, большинство из которых не будут локальными для tasktracker.

Наконец, отношения блока, разделения и файла можно суммировать следующим образом:

                                                             block boundary
|BLOCK           |    BLOCK       |   BLOCK        |   BLOCK ||||||||
|FILE------------|----------------|----------------|---------|
|SPLIT            |                |                |        |

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