Поиску недостаточно скачать одну веб-страницу. Нужно обойти множество сайтов, сохранить документы, извлечь слова и ссылки, построить индекс и повторять обработку по мере обновления интернета. Данные должны помещаться на дисках, а расчёты — завершаться за приемлемое время. Одна машина постепенно становится ограничением по обоим направлениям.
Можно купить более мощный сервер. Другой подход — объединить много серверов и разделить между ними данные и работу. Такую группу называют кластером. Вместе с дополнительными дисками и процессорами появляются новые вопросы: как найти нужную часть файла, что делать при отказе узла и как собрать общий результат?
История Hadoop
В 2003 году Google описала GFS, файловую систему для больших распределённых нагрузок. В 2004 году вышла работа о MapReduce — модели, позволяющей задавать обработку отдельных записей и объединение результатов, передавая распределение работы системе.
Эти идеи повлияли на открытый поисковый проект Nutch. В Nutch появились распределённая файловая система и реализация MapReduce. В 2006 году эти компоненты выделились в Hadoop. Получилась открытая платформа, которую можно развивать и использовать за пределами одной поисковой компании. Hadoop не является опубликованным исходным кодом внутренней системы Google.
Hadoop стал привлекателен возможностью добавлять обычные серверы, хранить большие объёмы и выполнять массовую обработку. Отказ одного диска при этом должен быть предусмотренным событием: с ростом числа устройств рассчитывать на вечную исправность каждого нельзя.
До появления таких систем рост объёма данных часто встречали увеличением мощности одного сервера: ставили больше дисков, памяти и процессоров. Этот способ остаётся разумным, пока одна машина справляется с объёмом и временем обработки. Но у него есть предел: сервер имеет конечное число слотов и каналов ввода-вывода, а его отказ останавливает всю работу. Hadoop предложил масштабировать задачу добавлением узлов. Это горизонтальное масштабирование: набор разбивают на части, а не пытаются прочитать его целиком одной машиной.
Дело было не только в том, чтобы вместить данные. Допустим, копии веб-страниц уже разложены по десяти серверам. Для нового индекса нужно прочитать их все, разобрать документы и объединить сведения об одинаковых словах. Перетаскивать весь набор на один сервер для каждого расчёта дорого: его сеть и процессор снова станут общим ограничением. Выгоднее отправить программу к данным, обработать части на месте и передать между узлами промежуточный результат.
При этом разработчику поискового алгоритма не хочется заново писать обработку каждого отказа диска и каждого пропавшего рабочего процесса. Платформа берёт общие механизмы на себя: хранит копии, распределяет задачи и позволяет повторить утраченную часть работы. Программа задаёт смысл расчёта — например, какие слова входят в индекс. Это и сделало подход полезным за пределами поиска: для журналов событий, больших выгрузок и регулярных аналитических расчётов.
Основные компоненты Hadoop
Hadoop — семейство компонентов для распределённого хранения и вычислений. У основных частей разные роли:
| Компонент | На какой вопрос отвечает |
|---|---|
| HDFS | Где лежат файлы и как прочитать их при отказе отдельного узла? |
| YARN | На каких узлах и с каким объёмом ресурсов запустить приложение? |
| MapReduce | Как разделить обработку записей и собрать результат по ключу? |
| Hadoop Common | Какие общие библиотеки и средства нужны остальным компонентам? |
Например, файл журналов лежит в HDFS. Приложение MapReduce считает запросы по адресам страниц. YARN выделяет процессы и ресурсы для выполнения. Загрузка файла, выделение ресурсов и расчёт выполняются отдельными действиями.
Три разных ограничения
Проверим это на наборе журналов объёмом 10 ТБ. Каждую ночь из него нужно построить новый поисковый индекс. У задачи сразу три ограничения:
| Ограничение | Что происходит на одной машине | Какая часть Hadoop помогает |
|---|---|---|
| Вместимость и отказ диска | Файлы могут не поместиться, потеря диска уничтожит часть входа | HDFS размещает блоки на нескольких DataNode и хранит копии |
| Время расчёта | Один процесс последовательно читает и разбирает весь объём | MapReduce делит вход на задачи и объединяет промежуточные результаты |
| Конкуренция за ресурсы | Индекс спорит за память и CPU с другими расчётами | YARN выделяет ресурсы приложениям и наблюдает за запущенными процессами |
На одном рабочем узле могут одновременно действовать DataNode и NodeManager. HDFS отвечает за байты, YARN — за запуск процессов, MapReduce — за логику пакетного расчёта. Такая граница помогает диагностировать сбой: отсутствующий блок, ожидание свободной памяти и неверный результат программы исправляют по-разному.
Как проходит один расчёт
Пусть журнал уже закрыт и лежит в HDFS. Клиент отправляет задание. YARN выделяет процессы на узлах, а MapReduce назначает им части входа. Процесс узнаёт через HDFS, где лежат нужные блоки, читает их с DataNode и создаёт промежуточные пары «ключ — значение». Данные одинакового ключа собираются вместе; итог записывается новым файлом. Позже другой процесс может прочитать этот результат. Вычисление не переписывает исходный журнал на месте.
Если узел с одной частью журнала пропал, HDFS может предложить её копию на другом DataNode. Вычислительную задачу для потерянной части запускают повторно. Это две разные формы восстановления: репликация данных сохраняет вход, повтор задачи возвращает расчёт. Они не защищают от логической ошибки: программа, дважды неверно считающая показатель, получит неверный результат даже при исправном кластере.
Что Hadoop позволил делать
Платформа подошла для пакетной обработки: накопить большой набор и обработать его целиком за ограниченное время. Важна пропускная способность — сколько данных удаётся прочитать и преобразовать за час, — а не минимальная задержка одиночного запроса. Поиск страницы для одного пользователя обслуживает поисковый сервис, а подготовка большого индекса может выполняться пакетным расчётом.
В аналитике этот подход позволил дольше сохранять исходные журналы и выгрузки, распределять их обработку между серверами и строить новые расчёты поверх уже собранных данных. Добавление узлов увеличивало суммарные диски и вычислительные ресурсы. Оно не делало любой алгоритм автоматически быстрее: общий обмен по сети и неравномерное распределение работы могли стать ограничением.
Представим, что почти все строки имеют один ключ unknown. После распределения каждая map-задача быстро обработает свою часть, но сведения об этом ключе придут в одну группу reduce. Остальные работники закончат, а один будет считать и записывать огромную группу. Дополнительные узлы не устранят перекос ключей. Инженер сначала смотрит размер входа, число задач, объём передачи между этапами и распределение ключей, а уже потом увеличивает кластер.
Hadoop и Data Lake
В Data Lake, озере данных, сохраняют большие наборы для дальнейшей обработки: исходные журналы, очищенные события, подготовленные результаты. HDFS может служить файловой основой такого озера. Но одной файловой системы мало: нужны понятные каталоги, форматы, правила доступа и сведения о структуре данных.
Hadoop встречается в уже построенных платформах с HDFS, YARN и общим каталогом таблиц. Для новых систем также используют объектное хранение — например S3 — и отдельно запускаемые вычислительные мощности. У объектного хранилища другой интерфейс: объект получают по ключу через API, а не через тот же набор операций распределённой файловой системы. Поэтому это выбор архитектуры, а не просто другое название HDFS.
Ни число строк, ни размер «больше 32 GB» сами по себе не требуют Hadoop. Если данные удобно обрабатываются PostgreSQL или программой на одной машине, кластер может добавить больше сложности, чем пользы. Его смысл появляется там, где распределение хранения и работы оправдывает сеть, настройку и обслуживание нескольких узлов.
HDFS и S3: что меняется для программы
В HDFS программа открывает файл по пути: NameNode сообщает, на каких DataNode находятся его блоки. В S3 программа обращается к объекту по ключу внутри бакета — контейнера объектов. Например, logs/2026/part-01.parquet выглядит как путь, но в обычном S3-бакете это ключ с префиксом. Внутренние диски и копии обслуживает система объектного хранения; клиент не выбирает DataNode.
| Свойство | HDFS | S3 |
|---|---|---|
| Организация | Файлы, каталоги и блоки в кластере | Объекты, ключи и бакеты |
| Размещение вычислений | Можно выполнять задачи рядом с репликами блоков | Обычно вычислительный кластер обращается к отдельному хранилищу по сети |
| Изменение имени | Операция с метаданными файловой системы | Для обычных бакетов перенос через файловый коннектор обычно означает копирование и удаление |
| Масштабирование | Нужно планировать диски и узлы HDFS; вычисления можно развивать отдельно | Хранение и вычислительные мощности обычно масштабируют независимо |
У обоих вариантов есть сценарии Data Lake. Spark умеет читать HDFS и обращаться к S3 через коннектор S3A, но одинаковый вызов чтения не делает свойства хранилищ одинаковыми. Например, алгоритм публикации результата через переименование каталога нельзя без проверки переносить из HDFS в объектное хранилище. Для него применяют подходящие механизмы фиксации файлов или табличные форматы.
Amazon S3 обеспечивает строгую согласованность чтения после записи и операций перечисления. Транзакции над несколькими объектами требуют отдельного механизма. Свойства другого S3-совместимого продукта нужно проверять отдельно.