Learning Platform
Глоссарий Troubleshooting
Урок 05.01 · 25 мин
Средний
AvroContainer FormatObject Container FileSync MarkerData BlocksCompression Codecs

Контейнерный формат

Object Container File

Apache Avro определяет два уровня: формат сериализации (encoding отдельных значений) и контейнерный формат (как записи группируются в файл). Object Container File (OCF) — стандартный контейнер для хранения Avro-записей вместе со схемой.

Ключевое отличие от Parquet и ORC: метаданные Avro находятся в начале файла, а не в конце. Ридер последовательно читает header, затем data blocks — без seek к концу. Это делает формат пригодным для потоковой обработки: можно начать десериализацию, не зная размера файла.

Структура Object Container File

Magic: Obj + 0x01 (4 байта)

4 байта: 0x4F 0x62 0x6A 0x01 — три ASCII-символа 'Obj' + байт версии 0x01. Идентификатор формата Avro OCF.
File MetadataAvro map, сериализованная в бинарном формате. Обязательные ключи: avro.schema (полная JSON-схема записей), avro.codec (кодек компрессии). Можно добавлять пользовательские ключи.

Sync Marker (16 random bytes)

16 случайных байт, уникальных для каждого файла. Генерируются при создании. Разделитель блоков и маркер целостности данных.
Data Block 0Каждый блок: long count (число объектов), long size (размер сериализованных данных в байтах), сами объекты, 16-байтовый sync marker.
Data Block 1Блоки идут последовательно. Можно начать чтение с любого блока, найдя sync marker в потоке.
...Количество блоков зависит от объёма данных и настроек sync interval при записи.
TIP

Parquet и ORC читают файл с конца — сначала footer, потом данные. Avro читает с начала — сначала header со схемой, потом последовательно блоки. Это принципиальная архитектурная разница: Avro оптимизирован для потоковой записи и чтения, а Parquet/ORC — для random access к колонкам.

Magic Bytes

Первые 4 байта файла — сигнатура формата:

БайтHexСимволЗначение
00x4FO
10x62b
20x6Aj
30x01Версия формата (1)

Три символа Obj + байт версии. Текущая и единственная версия — 0x01. Для сравнения: Parquet использует PAR1 (4 ASCII-символа), ORC — ORC (3 символа без байта версии).

NOTE

Байт 0x01 — не ASCII-символ, а числовое значение. Если вы откроете Avro-файл в текстовом редакторе, увидите Obj + невидимый символ (SOH — Start of Heading в ASCII-таблице). В hex-дампе: 4F 62 6A 01.

File Metadata

Сразу после magic bytes следует file metadata — Avro map<string, bytes>, сериализованная в бинарном формате Avro (block encoding для map, подробнее в уроке 03). Два ключа обязательны:

File Metadata Map
avro.schemaJSON-строка с полной схемой записей в файле. Writer's schema — схема, с которой данные были записаны. Используется ридером для десериализации.
avro.codecИмя кодека компрессии: null, deflate, snappy, bzip2, xz, zstandard. Если ключ отсутствует — подразумевается 'null' (без компрессии).
Пользовательские ключиПроизвольные метаданные: авторство, timestamp создания, pipeline ID и т.д. Ключи с префиксом 'avro.' зарезервированы спецификацией.

Ключ avro.schema содержит полную JSON-схему всех записей в файле. Это принципиальное решение Avro: схема путешествует с данными. В Parquet схема хранится в Thrift-сериализованном footer, в ORC — в Protobuf-сериализованном footer. Avro хранит JSON-строку прямо в header.

Пример значения avro.schema:

{
 "type": "record",
 "name": "User",
 "namespace": "com.example",
 "fields": [
 {"name": "id", "type": "long"},
 {"name": "name", "type": "string"},
 {"name": "email", "type": ["null", "string"], "default": null}
 ]
}
WARNING

Метаданные сериализуются как Avro map в бинарном формате — не как JSON. Чтобы прочитать metadata map, ридер уже должен уметь декодировать базовые Avro-типы: long (zigzag variable-length), string (length + UTF-8), bytes (length + raw bytes). Парсинг header — это bootstrapping: минимальный Avro-декодер нужен ещё до чтения схемы.

Sync Marker

После metadata map записываются 16 байт sync marker — случайное значение, уникальное для каждого файла. Sync marker выполняет три функции:

  1. Разделитель блоков — маркирует конец каждого data block
  2. Восстановление позиции — позволяет найти начало следующего блока при повреждении данных
  3. Защита от конкатенации — если два файла склеить cat a.avro b.avro, ридер обнаружит смену sync marker

Sync marker генерируется один раз при создании файла и повторяется после каждого data block. 16 байт (128 бит) дают пространство значений 2^128 — вероятность ложного совпадения со случайными данными пренебрежимо мала.

TIP

Sync marker в Avro аналогичен magic number в начале каждого column page в Parquet, но работает иначе. В Parquet маркеры одинаковы для всех файлов (фиксированные). В Avro sync marker уникален для каждого файла — это позволяет детектировать конкатенацию и повреждения.

Data Blocks

Основная структура хранения данных. Каждый блок содержит группу сериализованных объектов, записанных подряд:

Структура Data Block

Object Count (Avro long)

Avro long (variable-length zigzag encoding). Количество объектов (записей) в этом блоке. Зависит от sync interval при записи.

Block Size in bytes (Avro long)

Avro long — размер сериализованных данных в байтах ПОСЛЕ компрессии (если avro.codec != null). Позволяет пропустить весь блок без десериализации.
Serialized ObjectsОбъекты сериализованы подряд в Avro binary encoding — без разделителей между ними. Если кодек != null — весь блок сжат целиком одним вызовом компрессора.

Sync Marker (16 байт — копия из header)

Те же 16 байт, что записаны в header файла. Маркер конца блока. Позволяет ридеру верифицировать целостность и синхронизировать позицию.

Block size указывает размер после компрессии. Это позволяет эффективно пропускать блоки: ридер читает count и size, затем выполняет seek на size байт + 16 (sync marker), не декодируя содержимое.

Параллельное чтение

MapReduce и Spark делят файл на splits по диапазонам байт. Каждый reader получает свой диапазон и сканирует его на наличие sync marker. Найдя маркер, reader начинает чтение со следующего полного блока. Это обеспечивает параллельную обработку без центрального координатора.

Алгоритм:

  1. Reader получает диапазон [start, end) файла
  2. Если start > 0 — seek вперёд, сканируя по 16 байт за раз, ища sync marker
  3. Нашёл sync marker → следующие байты — начало нового блока (count)
  4. Читает блоки, пока не выйдет за end
NOTE

В отличие от Parquet, где параллелизм определяется row group offsets из footer (точные позиции), Avro требует линейного сканирования для поиска sync marker. Это делает начало чтения чуть медленнее, но зато не требует предварительного чтения footer.

Кодеки компрессии

Avro поддерживает шесть кодеков компрессии. Кодек указывается в avro.codec metadata и применяется ко всему содержимому data block целиком — объекты сжимаются вместе, не по отдельности:

КодекСтандартХарактеристики
nullБез компрессии. Минимальный CPU overhead. По умолчанию.
deflateRFC 1951zlib без header (raw deflate). Хорошее сжатие, умеренная скорость.
snappyGoogle SnappyБыстрая компрессия и декомпрессия. В Avro: data + 4-byte CRC32.
bzip2Высокое сжатие, медленная скорость. Блочный алгоритм.
xzLZMA2Максимальное сжатие, самая медленная компрессия. Для архивов.
zstandardZstd (Facebook)Настраиваемый баланс скорости и сжатия. Рекомендуется для новых проектов.
Сравнение кодеков Avro

Snappy — скорость

Snappy: приоритет скорости. ~250 MB/s компрессия, ~500 MB/s декомпрессия. Степень сжатия ~1.5-2x. Добавляет CRC32 checksum к каждому сжатому блоку.

Быстрая компрессия и декомпрессия
CRC32 checksum per block
Скромное сжатие (~1.5–2x)

Zstandard — баланс

Zstandard: настраиваемый уровень 1–22. На уровне 3 — скорость близка к Snappy, сжатие ближе к deflate. Поддерживает dictionary compression.

Настраиваемый уровень (1–22)
Хорошее сжатие при высокой скорости
Dictionary compression

XZ — максимальное сжатие

XZ (LZMA2): максимальное сжатие среди всех кодеков. Скорость компрессии ~10–30 MB/s. Декомпрессия быстрее. Для write-once архивного хранения.

Лучшее соотношение сжатия
Очень медленная компрессия
Высокое потребление CPU и памяти

NOTE

Snappy в Avro отличается от «чистого» Snappy: после каждого сжатого блока добавляется 4-байтовый CRC32 checksum. Ридер Avro обязан проверять CRC32 при декомпрессии — это защита целостности на уровне отдельного блока. Другие форматы (Parquet, ORC) используют Snappy без CRC32, полагаясь на checksums уровня файловой системы (HDFS block checksums).

Расположение метаданных определяет паттерн использования формата:

Header-first (Avro):

  • Запись: header пишется один раз, блоки дописываются последовательно
  • Чтение: начинаем с начала, не нужен random access
  • Подходит: потоковая обработка, append-heavy workloads, pipe между процессами
  • Не подходит: аналитические запросы (нет column-level access, нет predicate pushdown)

Footer-first (Parquet, ORC):

  • Запись: данные пишутся последовательно, footer записывается в конце
  • Чтение: seek к концу → footer → seek к нужным column chunks
  • Подходит: аналитические запросы, column pruning, predicate pushdown
  • Не подходит: потоковая обработка (нужен весь файл для чтения footer)

Сравнение контейнеров: Avro vs Parquet vs ORC

ХарактеристикаAvro OCFParquetORC
Magic bytesObj + 0x01 (4 байта)PAR1 (4 байта)ORC (3 байта)
Расположение схемыHeader (начало файла)Footer (конец файла)Footer (конец файла)
Сериализация метаданныхAvro binaryApache ThriftProtocol Buffers
Маркеры целостности16-byte sync marker (CRC per page)
Единица данныхData Block (row-oriented)Row Group / Column ChunkStripe / Column Streams
Параллельное чтениеScan для sync markerПо Row Group offsets из footerПо Stripe offsets из footer
Потоковая запись Да — header пишется первым Нет — footer в конце Нет — footer в конце
КомпрессияPer data block (все колонки)Per column pagePer column stream

Ключевые выводы

  1. Object Container File — контейнер Avro с header-first архитектурой: magic bytes → metadata map → sync marker → data blocks
  2. Magic bytes Obj + 0x01 (hex: 4F 62 6A 01) идентифицируют формат и версию
  3. Sync marker (16 random bytes) разделяет блоки и обеспечивает параллельное чтение через scan
  4. Data block = count + size + serialized objects + sync — самодостаточная единица, компрессия применяется ко всему блоку
  5. Схема путешествует с даннымиavro.schema в header позволяет десериализовать файл без внешнего schema registry
  6. Zstandard — рекомендуемый кодек для новых проектов (настраиваемый баланс скорости и сжатия)

Проверьте понимание

Результат: 0 из 0
Аналитический
Вопрос 1 из 4. Avro OCF (Object Container File) хранит метаданные и схему в header (начало файла). Parquet и ORC хранят метаданные в footer (конец). Какое практическое следствие этой разницы для потоковой обработки?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6