Hdfs

HDFS Shell

$hdfs dfs -<command> -<option> <URI>

#Листинг корневой директории
$hdfs dfs -ls /

URI

hdfs://localhost:8020/user/home
#hdfs:// - Schema
#localhost:8020 - authority
#/user/home - HDFS path

#Local
file:///to/path/file3

#HDFS
hdfs://localhost/to/path/dir

#fs.default.name=hdfs://localhost
/to/path/dir

HDFS

  • Fault Tolerant - Данные не теряются, если выходят из строя диски или сервера.
  • Используется обычное "Железо", "Дешевое" серверное оборудование
  • Один раз записали/много раз прочтиал

HDFS хорошо подходит для
1. Хранения больших файлов
- Терабайты, петабайты …
- Миллионы (но не миллиарды) файлов
- Файлы размером от 100мб
2. Стриминг данных
- Паттерн "write once/ read-many times"
- Оптимизация под последовательное чтение (нет операциям произвольного чтения)
- Операция append появилась в Hadoop 0.21

HDFS не подходит для
1. Low-latency reads
- Высокая пропускная способность вместо быстрого доступа к данным
- HBase помогает решать эту проблему
2. Большое количество небольших файлов
- Лучше миллион больших файлов, чем миллиард маленьких
3. Многопоточная запись
- Один процесс записи на файл
- Данные дописываются в конец файла
- Нет поддержки записи по смещению

Архитектура

brRwQVfQY9JMm1.jpg
Namenode
- файловое пространство (namespace)
- мета-информацию
- расположение блоков файлов

- Запускается на 1й (выделенной) машине
- Чем больше оперативной памяти тем больше файлов может быть
- Сервер должен быть очень надежным

Datenode
- Хранит и отдает блоки данных
- Отправляет ответы о состоянии на Namenode
- Запускается на каждой машине кластера

Secondary Namenode
- периодически обновляет fsimage
- Требует то же железо, что и Namenode
- (!) Не используется для high-availability, т.е. это не backup для Namenode

Файлы и блоки

xAe4vzhYgNpp2y.jpg

- Файлы в HDFS состоят из блоков (блок - единица хранения данных)
- Управляется через Namenode
- Хранится на Datanode

Реплицируются по машинам в процессе записи
- Оддин и тот же блок хранится на нескольких Datanode
- фактор репликации по умолчанию равен 3
- это нужен для fault-tolerance и упрощения доступа

Блоки
- Стандартный размер блоков 64мб или 128мб
- Основной мотив этого - снизить стоимость seek time по сравнению со скоростью передачи данных (transfer rate)

Репликация блоков
- Namenode определяет, где располагать блоки

- Баланс между надежностью и производительностью
| - Попытка снизить нагрузку на сеть (bandwidth)
| - Попытка улучшить надежность путем размещения реплик в разных стойках

- Фактор репликации по умолчанию равен 3
| - 1-я реплика на локальную машину
| - 2-я реплика на другую машину из той же стойки
| - 3-я реплика на машину из другой стойки

Hadoop знает топологию сети, в частности знает какие сервера находятся в одной стойке. Поэтому когда возникает необходимость сделать репликации, то для одной выбирается другой сервер из этой же стойки, а для другой выбирается сервер из другой стойки. Это в целом не единственное условие при выборе сервера. Более того, это условие может нарушаться и, в принципе, такое поведение можно отключить. В целом для пользователя не так принципиально, на каком именно сервере располагаются реплики. Это важно для Hadoop, который старается соблюсти баланс между скоростью доступа (в одной стойке быстрее) и надежностью (надежней хранить в разных стойках).

Итак, как все происходит на самом деле: на каждой ноде кластера есть файл, в котором описывается кластер (не будут использовать слово "топология", т.к. оно непонятное). Что есть в этом файле? Во-первых, он содержит список всех серверов. Кроме того, сервера объединены в группы: скорость передачи данных внутри одной группы выше, чем скорость передачи данных в другую группу. Обычно, для каждой стойки ставят один свитч, поэтому скорость передачи данных внутри одной стойки выше, чем передача данных в другую стойку. В общем случае, группы могут выделяться не по стойкам. У нас, например, один свитч ставится на несколько стоек, поэтому в одной группе находятся сервера из разных стоек. Для упрощения повествования я не использовал группы и свитчи, а ограничился стойками.

Сам файл с описанием кластера формируется обычно автоматически скриптами из простого файла, в котором перечислено, какой сервер под каким свитчем находится.

Клиент может находится как внутри кластера, так и снаружи. В первом случае первая реплика будет располагаться локально на том же хосте. Если место на хосте закончится, то реплика будет записываться на другой хост. Это далеко не единственный минус использования клиента внутри кластера, но при этом не самый страшный, т.к. можно запустить балансировку в hdfs и "лишние" блоки переедут на другой хост.

Если клиент находится снаружи кластера, то первая реплика располагается на произвольной машине кластера.

Что касается изменения стратегии расположения реплик, то начиная с версии 0.21 ее можно изменить. Более того, можно самому спрограммировать нужную стратегию. Когда такое может понадобиться? Например, можно использовать стратегию, в которой все блоки одного файла хранятся преимущественно на одном хосте. Это может использоваться для чтения всех блоков этого файла одним маппером при использовании CombineInputFormat (но это уже довольно тонкие вещи, пока вам достаточно знать, что изменить стратегию можно).

Расчет размер блока
seek time = 10 ms (время перемещение головки от файла к файлу)
transer rate = 100MB/s (пропускная способность сети)
Размер блока должен быть таким что бы Seek time достигал всего 1% от transfer rate?
10ms = 1% тогда 100% = 1s
за 1s мы можем считать 100МБ
Размер блока получился 100МБ

Больше размер блока -> меньше блоков
Меньше блоков -> больше файлов в FS

200ТБ = 209,715,200МБ
При размере блока 64МБ: 209,715,200МБ / 64Мб = 3,276,800 блоков
При размере блока 128МБ: 209,715,200МБ / 128Мб = 1,638,400 блоков

Взаимодействие клиента и демонов

Чтение
1) Обратились к namenode за информацией о расположении файла
2) namenode сообщает полную информацию о файле, включая количество реплик и места их хранения
3) обращаемся к какой-то datanode (кстати, как выбираем, к какой именно?)
4) если чтение не удалось, то на клиенте надо обработать read fialure и выбрать следующую datanode
5) шаг 4 повторять до тех пор, пока чтение не пойдет успешно, или пока не кончатся реплики, полученные от nadenode на шаге 2

В ответ на запрос о местоположении блока файла от клиента к Namenode, клиент получает список Datanode с этим блоком, отсортированный по "близости" к клиенту. Близость определяется из топологии сети. Если клиент расположен на сервере, на котором есть нужный блок, то этот сервер будет первым в списке datanode. Следующим будет сервер из той же стойки (если на нем есть реплика нужного блока) и т.д.
Если происходит ошибка при чтении блока, то клиент попытается считать блок по следующему адресу из списка. При этом клиент запомнит "плохую" datanode и следующие блоки не будет с нее считывать.
Q2KwLJf9wBXy2j.jpgЗапись
1)Клиент делает запрос к Namenode на создание блока. Namenode определяет, на каких хостах должны быть расположены реплики и передает эту информацию клиенту.
2)Клиент начинает писать данные блока на первую ноду из списка и сообщает Datanode, на какой следующий хост нужно реплицировать данные. Запись происходит небольшими порциями (по 4Кб). После получения каждой порции данных, Datanode передает ее следующей Datanode из списка.
3)Вторая Datanode также получает данные порциями и передает их следующей Datanode.
4)Таким образом получается некий pipe, данные в котором передаются последовательно по цепочки по всему списку хостов, на которых должны находится реплики.
GrqRvOfNkZylmz.jpg

Namenode

Использование памяти
Для быстрого доступа вся мета-информация о блоках хранится в ОЗУ Namenode
Чем больше кластер, тем больше ОЗУ требуется

Namenode Federation (Hadoop 2+)
- Каждая Namenode управляет частью блоков
- Горизонтальное масштабирование Namenode
- Поддержка кластеров из тысячи машин

Fault-tolerance
Если Namenode падает, то HDFS не работает
Namenode - это единая точка отказа (single point of failure)
- Должная работать на отдельной надежной машине
- Обычно, это не бывает проблемой

Fault-tolerance в Hadoop 2+
High Availability Namenode
Процесс Active Standby всегда запущен и берет на себя управления в случае падения Namenode

Доступ к HDFS

- Direct Access
| - Взаимодействует с HDFS с помощью нативного клиента
| - Java, C++
- Через Proxy Server
| - Доступ к HDFS через Proxy Server - middle man
| - Серверы REST, Thrift и Avro

Пока не указано иное, содержимое этой страницы распространяется по лицензии Creative Commons Attribution-ShareAlike 3.0 License