Apache Avro
Apache Avro — это система сериализации данных с открытым исходным кодом, разработанная в рамках проекта Apache Hadoop. Она предоставляет компактный, быстрый и бинарный формат сериализации, использующий JSON для определения схем данных и поддерживающий богатые структуры данных, включая вложенные и типизированные записи, массивы и перечисления. Avro спроектирован для работы в распределённых системах, обеспечивая эффективную передачу данных между процессами и долговременное хранение.
История
Разработка Avro началась в 2009 году в компании Cloudera как часть экосистемы Hadoop для замены более ранних и менее эффективных систем сериализации, таких как Apache Thrift и Google Protocol Buffers. Основными авторами выступили Дуг Каттинг (Doug Cutting, создатель Hadoop) и его коллеги. В 2010 году проект был передан в инкубатор Apache Software Foundation, а в 2011 году получил статус полноценного проекта верхнего уровня. Avro быстро стал стандартом де-факто для сериализации в экосистеме Hadoop, особенно в связке с Apache Hive, Apache Pig и Apache Spark. В последующие годы формат был адаптирован для использования в системах потоковой передачи данных, таких как Apache Kafka и Apache Flink, а также в базах данных, например, Apache Cassandra и Apache HBase.
Ключевые особенности
Схемы данных на JSON
Основным отличием Avro от многих других систем сериализации является использование JSON для описания схемы данных. Схема определяет типы полей, их имена, порядок и возможные значения. Это делает схемы человекочитаемыми и легко редактируемыми. Пример схемы для записи о пользователе: ``json { "type": "record", "name": "User", "namespace": "com.example", "fields": [ {"name": "name", "type": "string"}, {"name": "age", "type": "int"}, {"name": "email", "type": ["null", "string"], "default": null} ] } ``
Бинарная сериализация
Данные в Avro сериализуются в компактный бинарный формат, который не содержит метаданных о схеме — только сами значения. Размер бинарного представления значительно меньше, чем у текстовых форматов (JSON, XML), и сравним с Protocol Buffers или Thrift. Это обеспечивает высокую скорость передачи и низкую загрузку сети.
Динамическая типизация и эволюция схем
Avro поддерживает динамическую типизацию: приложение может читать данные, записанные по одной схеме, используя другую схему (схему чтения). Это позволяет изменять структуру данных без перезаписи всех существующих записей. Правила совместимости включают добавление/удаление полей с значениями по умолчанию, изменение типов в пределах совместимых групп и переименование полей. Это делает Avro удобным для долгоживущих систем, где схемы эволюционируют со временем.
Сжатие
Avro поддерживает встроенное сжатие данных на уровне блоков. Поддерживаются кодеки: null (без сжатия), deflate (алгоритм zlib), snappy, zstandard (zstd) и bzip2. Сжатие значительно уменьшает размер хранимых данных и ускоряет их передачу по сети, особенно при работе с большими объёмами.
Поддержка языков программирования
Avro имеет официальные реализации для Java, C, C++, C#, Python, Ruby, PHP, JavaScript, Perl, Rust, Go и других языков. Это обеспечивает кроссплатформенную совместимость и возможность обмена данными между системами, написанными на разных языках.
Архитектура и устройство
Формат файла
Файл Avro (расширение .avro) состоит из трёх частей:
- Заголовок: содержит метаданные, включая схему данных (в формате JSON), информацию о кодеках сжатия и синхронизационные маркеры.
- Блоки данных: каждый блок содержит последовательность записей, сериализованных в бинарном формате. Блоки могут быть сжаты независимо друг от друга. Между блоками вставляются 16-байтовые синхронизационные маркеры, позволяющие быстро находить начало следующего блока при чтении.
- Конец файла: не имеет специального маркера — файл заканчивается после последнего блока.
Схемы и сериализация
Сериализация в Avro основана на схеме. При записи данные кодируются в соответствии с определённой схемой. При чтении используется схема чтения, которая может отличаться от схемы записи. Avro автоматически сопоставляет поля по имени и типу, применяя правила эволюции. Это позволяет, например, читать старые данные с новой схемой, где добавлено поле со значением по умолчанию.
Синхронизация и разделение
Благодаря синхронизационным маркерам, файлы Avro можно легко разделять на части (splits) для параллельной обработки в распределённых системах, таких как Hadoop MapReduce или Spark. Каждый блок может быть обработан независимо, что обеспечивает высокую производительность при обработке больших данных.
Применение
Хранение больших данных
Avro является одним из основных форматов хранения в экосистеме Hadoop. Он используется для хранения данных в HDFS (Hadoop Distributed File System) как альтернатива текстовым форматам (CSV, JSON) и другим бинарным форматам (Parquet, ORC). Avro особенно эффективен для потоковой записи и чтения данных, когда требуется высокая скорость и компактность.
Потоковая передача данных
В системах потоковой обработки, таких как Apache Kafka, Avro используется для сериализации сообщений. Сочетание Avro с реестром схем (Schema Registry) позволяет централизованно управлять схемами и обеспечивать совместимость между продюсерами и консюмерами. Это критически важно для микросервисных архитектур и event-driven систем.
Обмен данными между системами
Avro часто применяется для обмена данными между различными компонентами распределённых приложений, написанными на разных языках программирования. Например, Java-приложение может записать данные в Avro-файл, а Python-скрипт — прочитать их без проблем с совместимостью.
Базы данных и хранилища
Некоторые базы данных, например, Apache Cassandra и Apache HBase, поддерживают Avro как формат сериализации для своих данных. Это позволяет эффективно хранить сложные структуры и обеспечивать эволюцию схем.
Сравнение с другими форматами
Avro vs Protocol Buffers (Protobuf)
- Схемы: Avro использует JSON, Protobuf — собственный бинарный формат
.proto. - Эволюция: Avro поддерживает более гибкие правила эволюции (добавление/удаление полей с default, переименование).
- Производительность: Protobuf обычно немного быстрее на сериализации/десериализации, но Avro обеспечивает меньший размер данных за счёт отсутствия метаданных в каждой записи.
- Языковая поддержка: Protobuf имеет более широкую поддержку языков, но Avro также покрывает большинство популярных языков.
Avro vs Thrift
- Схемы: Thrift использует собственный IDL (Interface Definition Language), Avro — JSON.
- Совместимость: Avro обеспечивает лучшую эволюцию схем и динамическую типизацию.
- Производительность: Thrift может быть быстрее на простых структурах, но Avro часто выигрывает по размеру данных.
- Экосистема: Avro глубже интегрирован в экосистему Hadoop и Kafka.
Avro vs Parquet
- Назначение: Avro — формат строкового хранения (row-oriented), Parquet — колоночного (column-oriented). Avro лучше подходит для потоковой записи и чтения полных записей, Parquet — для аналитических запросов, где требуется чтение только нескольких столбцов.
- Сжатие: Parquet обеспечивает более эффективное сжатие для колоночных данных, Avro — для строковых.
- Эволюция схем: Avro поддерживает более гибкую эволюцию схем, Parquet — более ограниченную.
Интересные факты
- Название «Avro» происходит от названия британского авиастроительного предприятия Avro (A.V. Roe and Company), что отражает желание создателей сделать формат «парением над данными».
- Avro был одним из первых форматов, который интегрировал поддержку эволюции схем «из коробки», что стало важным преимуществом перед Thrift и Protobuf на момент его появления.
- В отличие от Protobuf и Thrift, Avro не требует генерации кода из схемы — данные могут читаться динамически, используя только JSON-схему. Это упрощает прототипирование и работу с динамическими данными.
- Avro активно используется в проектах Apache Kafka, Apache Hadoop, Apache Spark, Apache Flink, Apache Hive, Apache Pig и многих других.
Критика
Основные недостатки Avro включают:
- Отсутствие поддержки встроенных сложных типов: например, нет встроенного типа для даты/времени — их приходится моделировать через строки или целые числа.
- Меньшая производительность на простых операциях: по сравнению с Protocol Buffers, Avro может быть медленнее на сериализации/десериализации простых структур.
- Зависимость от схемы: хотя схема не обязана быть известна заранее, её отсутствие делает данные нечитаемыми. Это требует использования реестра схем или хранения схемы вместе с данными.
- Ограниченная поддержка в некоторых языках: реализации для менее популярных языков могут быть неполными или устаревшими.
Источники
- Apache Avro Documentation (avro.apache.org)
- Hadoop: The Definitive Guide, 4th Edition, Tom White
- Designing Data-Intensive Applications, Martin Kleppmann
- Apache Kafka Documentation (kafka.apache.org)
- Официальные руководства по Apache Spark, Apache Flink, Apache Hive
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →