Apache Iceberg. Архитектура и основные концепции
Заглянем под воду
Содержание
Ранние дни data lakes: хаос на складе
Если вы, как и я, при слове «аналитика» или «большие данные» представляете себе гигантскую кучу файлов, лежащих где‑то в даталейке (скорее всего, в S3), — вы не одиноки.
Раньше data lakes были очень простыми. Это были Parquet‑файлы, разложенные по директориям, которые соответствовали партициям. Если вы не знакомы с Parquet — это колоночный формат хранения, который очень эффективен для сканирования. А сканирование — самая частая операция в OLAP‑запросах: нужно прочитать кучу записей как можно быстрее и посчитать какую‑нибудь агрегацию.
Итак, вы скидываете Parquet‑файлы в S3 по жёстко заданным путям. А потом, в тёмные времена, писали MapReduce‑программы на Java, чтобы их обработать. Веселье, правда? Вы вручную фильтровали партиции и просто надеялись, что никто другой не пишет в то же место, пока вы читаете. Транзакций не было. Изменения схемы ломали пайплайны, а понять, какие данные актуальны, было кошмаром.
Hive: первый луч порядка
В 2008 году Hive изменил правила игры. Он принёс в data lakes табличные форматы, добавил схемы, партиции и — о чудо! — SQL‑интерфейс. Внезапно можно было написать select * from sales вместо 200‑строчной Java‑программы, втиснутой в функции map и reduce (о которых лучше не вспоминать).
Но скоро появились новые проблемы:
- Эволюция схемы была ограничена. Хотите добавить колонку? Ладно. А переименовать или удалить — придётся переписать всю таблицу, фактически скопировав её в другое место.
- Партиции были жёстко зашиты в структуру директорий. Если ошиблись при создании таблицы — всё, вы в ловушке. Медленные запросы или полная перезапись.
- Транзакций не было годами. Конкурентные записи портили данные.
- ACID наконец появился в 2014, но только для ORC‑файлов, и породил дельта‑файлы, требующие постоянной компрессии.
Всё это было построено для Hive. Другие движки могли подключаться к даталейку, но бесшовной работы не получалось.
Apache Iceberg: перезагрузка
В 2017 году инженеры Netflix посмотрели на этот бардак и решили начать с чистого листа. Они создали Iceberg — открытый табличный формат, который относится к файлам в даталейке как к настоящим таблицам базы данных, со всеми гарантиями, которые вы ждёте от транзакционной СУБД.
Как и в Hive, вы получаете SQL‑таблицы со схемами и партициями. Но в отличие от Hive, вы также получаете:
- Настоящие ACID‑транзакции
- Эволюцию схемы, которая действительно работает
- Путешествия во времени
- Скрытое партицирование, которое адаптируется под ваши запросы
- Возможность менять схему партицирования со временем
И ещё одно ключевое отличие: Hive хранил метаданные вне даталейка. Iceberg хранит метаданные прямо рядом с данными. Всё живёт в озере.
Как устроен Iceberg внутри
Давайте заглянем под капот. Iceberg организует таблицу в несколько слоёв — как матрёшка, только полезная.
1. Файлы данных (Data Files)
В самом низу лежат собственно данные — те самые Parquet‑ (или ORC‑, или Avro‑) файлы. Они неизменяемы: после записи их нельзя править. Если нужно обновить строку, Iceberg запишет новый файл (об этом позже). Это типично для аналитических систем, где данные чаще всего смотрят в прошлое, а прошлое, как известно, не меняется.
Хотя иногда хочется, да? «Эх, вернуть бы тот удачный коммит…»
2. Манифесты (Manifest Files)
Каждый манифест отслеживает набор файлов данных вместе со статистикой: количество строк, минимальные/максимальные значения для числовых колонок, информация о партициях и т.д. Именно это позволяет движкам запросов пропускать целые файлы, даже не открывая их. Например, если вам нужны продажи за январь, а в 47 файлах ничего за январь нет — Iceberg проигнорирует их, просто взглянув на метаданные.
Как и файлы данных, манифесты неизменяемы.
3. Списки манифестов (Manifest Lists)
Это списки манифестов. Каждый список указывает на кучу манифестов и хранит сводную статистику: сколько файлов в этих манифестах, какие партиции покрыты, какие диапазоны. Это добавляет ещё один уровень отсечения: если запрос фильтрует по январю 2025, Iceberg может пропустить целый список манифестов, если знает, что он покрывает только 2024 год.
Списки манифестов тоже неизменяемы.
4. Файл метаданных (Metadata File)
Это единый источник истины для таблицы. В нём живут схема, стратегия партицирования, свойства таблицы и, самое главное, история снапшотов.
Снапшот — это версия таблицы в конкретный момент времени. Представьте себе коммит в Git (если вы знакомы с Git, вам будет проще понять путешествия во времени, ветвление, теги и т.д.). В Iceberg снапшот фиксирует состояние таблицы и после создания замораживается навсегда.
Каждый снапшот имеет ID, метку времени и указывает на список манифестов.
И да, файлы метаданных тоже неизменяемы. Всё в Iceberg записывается один раз и никогда не меняется.
А как тогда добавлять данные?
Всё просто: вы пишете новые файлы на каждом уровне.
- Приходят новые данные — Iceberg пишет новые файлы данных.
- Создаётся новый манифест, указывающий на эти файлы.
- Создаётся новый список манифестов, ссылающийся на старые манифесты и новый.
- Создаётся новый файл метаданных со свежим снапшотом, который указывает на новый список манифестов.
Все старые файлы остаются на месте, нетронутыми. Именно это позволяет потом «путешествовать во времени» — возвращаться к предыдущим снапшотам.
Каталог: дружелюбный указатель
Хорошо, а как движок запросов узнаёт, где лежит этот самый файл метаданных? Ведь это какой‑то длинный путь в S3, вроде s3://my-bucket/data/sales/metadata/00001-1234567890.metadata.json. Копировать и вставлять такое — не самое приятное занятие.
Вот здесь на сцену выходит каталог. Он выступает в роли адресной книги: вы даёте таблице человекочитаемое имя (например, sales или meetups), а каталог хранит ссылку на актуальный файл метаданных. О каталогах мы подробно поговорим в следующем уроке.
Итог
Итак, архитектура Iceberg напоминает слоёный пирог:
- Файлы данных внизу (Parquet/ORC/Avro)
- Манифесты отслеживают файлы данных
- Списки манифестов организуют манифесты
- Файлы метаданных связывают всё вместе и хранят историю снапшотов
- Каталог снаружи даёт таблице удобное имя
Вся эта конструкция неизменяема — и именно это делает возможными путешествия во времени, ACID‑транзакции и безопасную эволюцию схемы.
Если Hive был как картотека с бумажками, которые постоянно теряются, то Iceberg — это отполированный цифровой архив, где каждый документ лежит на своём месте, а история изменений сохраняется навечно.
Что дальше?
В следующем уроке мы разберём каталоги Iceberg: как они работают, какие бывают (Hive Metastore, AWS Glue, Nessie) и как выбрать подходящий для вашего проекта.