Обзор протоколов обработки и хранения данных
And now for something completely different.... Летающий цирк Монти Пайтона о формате Parquet
Введение
В ландшафте современной инженерии данных выбор правильного протокола сериализации и обработки данных является критическим решением, которое влияет на производительность, взаимодействие и масштабируемость системы. Эти протоколы определяют, как данные структурируются, сериализуются, хранятся и передаются между различными системами в различных языках программирования.
В этой статье мы рассмотрим пять протоколов обработки данных, которые стали отраслевыми стандартами: MessagePack, Apache Avro, Protocol Buffers (protobuf), Apache Thrift и Apache Parquet. Каждый из них предлагает определенные преимущества и оптимизирован для конкретных случаев использования: от коммуникации в реальном времени до аналитики больших данных.
Независимо от того, создаете ли вы микросервисы, проектируете конвейеры данных или внедряете аналитические системы, понимание этих протоколов поможет вам принимать обоснованные архитектурные решения.
MessagePack
Общее описание
MessagePack — это формат бинарной сериализации, который описывает себя как "JSON, но быстрый и компактный". MessagePack обеспечивает эффективное бинарное представление данных, оптимизированное для передачи и хранения. В отличие от JSON, MessagePack предлагает значительные улучшения как в размере, так и в скорости обработки.
Ключевые концепции реализации
- Бинарный формат: данные кодируются в компактном бинарном формате, а не в текстовом.
- Отсутствие схемы: предварительно определенная схема не требуется, подобно JSON.
- Сохранение типов: автоматически сохраняет типы данных при сериализации.
- Минимальные накладные расходы: разработан для минимизации затрат на сериализацию.
Поддерживаемые типы данных
MessagePack поддерживает большое кол-во различных типов данных:
- Nil (null)
- Boolean (логический)
- Integer (целое число, со знаком/без знака, 8/16/32/64-бит)
- Float (с плавающей точкой, 32/64-бит)
- Raw bytes (сырые байты, бинарный формат)
- String (строка, UTF-8)
- Array (массив)
- Map (пары ключ-значение)
- Extension types (типы расширений для пользовательских структур данных)
Использование
MessagePack отлично подходит в сценариях, где:
- вам нужна более эффективная альтернатива JSON,
- коммуникация в реальном времени требует компактных сообщений, в т.ч. взаимодействие IoT устройств, а также передача большого количества данных по сети,
- важна гибкость схемы.
MessagePack используется в Redis в качестве протокола сериализации данных, а также в Fluentd в качестве внутреннего представления данных, увеличивая производительность при передаче логов.
Полезные рекомендации
1. Используйте для простых структур: MessagePack работает лучше всего с относительно плоскими структурами данных.
2. Используйте сжатие: для больших нагрузок комбинируйте MessagePack с алгоритмами сжатия.
3. Версионируйте свои данные: включайте поле версии в структуру данных для обработки изменений формата.
Apache Avro
Общее описание
Apache Avro — это система сериализации данных, разработанная в рамках проекта Apache Hadoop. Apache Avro обеспечивает компактный, быстрый, бинарный формат данных с богатыми структурами данных и формат файла-контейнера для хранения метаданных. Одной из отличительных особенностей Avro является его надежные возможности эволюции схемы, что делает его идеальным для систем, где структуры данных изменяются со временем.
Ключевые концепции реализации:
- На основе схемы: требует JSON-схемы для определения структуры данных. Файлы данных включают свою схему, что делает их самодокументируемыми.
- Эволюция схемы: поддерживает добавление, удаление и изменение полей с сохранением совместимости.
- Бинарное кодирование: использует компактное бинарное кодирование для эффективного хранения и передачи.
- Богатые структуры данных: поддерживает сложные вложенные типы данных.
- Файлы-контейнеры (Object Container Files): встроенная поддержка файловых контейнеров с метаданными.
- Поддержка сжатия (поддерживаемые кодеки сжатия deflate, xz, snappy, zstandard, bzip2).
Поддерживаемые типы данных
Avro поддерживает следующие примитивные типы:
- null
- boolean (логический)
- int (32-битное со знаком)
- long (64-битное со знаком)
- float (32-битное IEEE 754)
- double (64-битное IEEE 754)
- bytes (последовательность 8-битных беззнаковых байтов)
- string (последовательность символов Unicode)
- record (похоже на объекты/структуры)
- enum (перечисляемые значения)
- array (упорядоченные коллекции)
- map (неупорядоченные пары ключ/значение)
- union
- fixed (байтовый массив фиксированного размера)
Более подробно прочитать про типы можно на странице спецификации
Использование
Avro особенно хорошо подходит для:
- обработки больших данных в экосистемах Hadoop,
- платформ потоковой передачи событий (особенно с Kafka),
- систем, требующих эволюции схемы,
- хранения больших наборов данных с самоописательными схемами.
Schema Registry от Confluent для Apache Kafka использует Avro для обеспечения управления схемами в платформах потоковой передачи данных.
Полезные рекомендации
- Следуйте правилам эволюции схемы: придерживайтесь правил совместимости Avro при развитии схем.
- Добавляйте значения по умолчанию: предоставляйте значения по умолчанию для новых полей, чтобы поддерживать обратную совместимость.
Protocol Buffers (protobuf)
Общее описание
Protocol Buffers (protobuf) — это нейтральный к языку, нейтральный к платформе, расширяемый механизм для сериализации структурированных данных. Один из наиболее широко используемых форматов бинарной сериализации. Он определяет структуры сообщений в файлах .proto, которые компилируются в код, специфичный для языка, который обрабатывает сериализацию, десериализацию и проверку типов.
Ключевые концепции реализации
- Язык определения интерфейса: использует файлы .proto для определения структур сообщений.
- Генерация кода: компилирует схемы в код, специфичный для языка.
- Бинарный формат: компактный бинарный формат для эффективной передачи.
- Обратная/прямая совместимость: разработан для эволюции схемы через нумерацию полей.
- Строгая типизация: обеспечивает типы данных через сгенерированный код.
- Номера полей: каждое поле имеет уникальный номер, используемый в бинарном кодировании.
- Вложенные сообщения: поддерживает сложные вложенные структуры данных.
- Определения сервисов: может определять RPC-сервисы (особенно с gRPC).
Поддерживаемые типы данных
Protocol Buffers поддерживает следующие скалярные типы:
- double, float (числа с плавающей точкой)
- int32, int64, uint32, uint64 (целые числа)
- sint32, sint64 (целые числа со знаком, кодируются более эффективно чем int32, int64)
- fixed32, fixed64, sfixed32, sfixed64 (целые числа фиксированной ширины)
- bool (логическое значение)
- string (текст в кодировке UTF-8)
- bytes (произвольные последовательности байтов)
- enum (перечисляемые значения)
- message (композитный тип)
- repeated fields (массивы/списки)
- map (пары ключ-значение)
- oneof (тип объединения)
Использование
Protocol Buffers лучше всего подходит для:
- коммуникации микросервисов (особенно с gRPC),
- мобильных приложений с ограниченной пропускной способностью,
- систем, требующих строгой типизации и валидации,
- кросс-языковых сервисов с последовательными интерфейсами.
Полезные рекомендации
1. Тщательно планируйте номера полей: оставляйте пробелы в нумерации полей для будущих добавлений.
2. Никогда не изменяйте номера полей: после назначения номера полей никогда не должны меняться.
3. Документируйте определения сообщений: добавляйте ясные комментарии к файлам .proto.
4. Используйте известные типы: используйте стандартные определения для общих понятий (временные метки и т.д.).
Более подробно про все рекомендации можно прочитать на странице проекта
Apache Thrift
Общее описание
Apache Thrift — это фреймворк для масштабируемой разработки кросс-языковых сервисов. Thrift объединяет программный стек с механизмом генерации кода для создания сервисов, которые эффективно работают на нескольких языках программирования. Он использует свой собственный язык определения интерфейса (Interface Definition Language (IDL)) для определения типов данных и интерфейсов сервисов, которые затем компилируются в код на целевых языках.
Ключевые концепции реализации
- Многоуровневая архитектура: Разделяет транспорт, протокол, процессор и сервер.
- Идентификаторы полей: числовые идентификаторы для полей, обеспечивающие обратную совместимость.
- Абстракция транспорта: множество вариантов транспорта (TCP, HTTP и т.д.).
- Абстракция протокола: множество протоколов связи (бинарный, компактный, JSON).
- Обработка исключений: встроенная поддержка для определения и передачи исключений.
- Поддержка версионирования: механизмы для обработки различий в версиях.
Поддерживаемые типы данных
Thrift поддерживает следующие базовые типы:
- bool (логическое значение)
- byte (8-битное целое число со знаком)
- i16 (16-битное целое число со знаком)
- i32 (32-битное целое число со знаком)
- i64 (64-битное целое число со знаком)
- double (64-битное число с плавающей точкой)
- string (текст, кодированный в UTF-8)
- binary (некодированные последовательности байтов)
- list (упорядоченный список элементов)
- set (неупорядоченное множество уникальных элементов)
- map (пары ключ-значение)
- struct (похоже на классы или записи)
- enum (перечисляемые значения)
- union (подобно C-объединениям)
- exception (для обработки ошибок)
- typedef (псевдонимы типов)
Использование
- построение архитектур микросервисов с использование различных языков,
- кросс-языковые RPC-системы,
- высокопроизводительные интерфейсы сервисов,
- системы, требующие как определения данных, так и интерфейсов сервисов.
Полезные рекомендации
1. Тщательно проектируйте сервисы: инвестируйте время в продуманное проектирование интерфейса.
2. Используйте подходящие идентификаторы полей: назначайте идентификаторы полей с запасом для будущего расширения.
3. Выбирайте правильный протокол: выбирайте между бинарным, компактным или JSON в зависимости от потребностей.
Придерживайтесь стандарта, рекомендованного при использовании Thrift.
Apache Parquet
Общее описание
Apache Parquet — это формат столбцового хранения, разработанный для эффективной обработки и хранения данных. Parquet оптимизирован для работы со сложными структурами данных в больших объемах. В отличие от других обсуждаемых нами протоколов, которые в основном предназначены для сериализации сообщений, Parquet специально создан для аналитических рабочих нагрузок, где распространено чтение только определенных столбцов данных. Apache Parquet получил самое широкое распространение в большом количестве популярных фреймворков (apache iceberg, apache hudi), библиотеках (apache arrow) и аналитических БД (duckdb, clickhouse).
Ключевые концепции реализации
- Столбцовый формат: хранит данные по столбцам, а не по строкам.
- Сжатие: поддерживает несколько алгоритмов сжатия для каждого столбца.
- Организация страниц и групп строк: данные организованы в страницы и группы строк.
- Эволюция схемы: позволяет добавлять, удалять или изменять столбцы.
- Кодирование, специфичное для типа: использует специализированные кодировки для разных типов данных.
- Поддержка вложенных данных: эффективно обрабатывает сложные вложенные структуры.
Поддерживаемые типы данных
Parquet поддерживает следующие примитивные типы:
- boolean (логический)
- int32/int64 (целые)
- int96 (для временных меток)
- float/double (с плавающей точкой)
- byte array (для строк и бинарных данных)
- fixed length byte array (байтовый массив фиксированной длины)
Использование
Parquet полезен в следующих случаях:
- хранилищах данных и аналитике,
- обработке больших данных с Hadoop/Spark,
- хранении больших наборов данных для пакетной обработки,
- системах с колоночно-ориентированными шаблонами запросов,
- озерах данных и холодном хранилище.
Кроме того, стоит отметить, что в сообществе Prometheus идет активное обсуждение внедрения поддержки формата Parquet.
Заключение
MessagePack
Лучше всего подходит для простой и эффективной замены JSON, где важна гибкость схемы.
- Преимущества: не требуется схема, компактный бинарный формат.
- Ограничения: нет эволюции схемы, ограниченная безопасность типов.
- Сценарии использования: мобильные приложения, простые API, замена JSON для повышения производительности.
Apache Avro
Лучше всего подходит для систем, требующих эволюции схемы.
- Преимущества: отличная эволюция схемы, самоописание, компактный формат.
- Ограничения: требует определения схемы, меньше инструментария для некоторых языков.
- Сценарии использования: экосистема Hadoop, развивающиеся конвейеры данных, интеграции с Kafka.
Protocol Buffers
Лучше всего подходит для строго типизированных интерфейсов сервисов с кросс-языковой совместимостью.
- Преимущества: отличный инструментарий, сильная безопасность типов, эффективное кодирование.
- Ограничения: меньшая гибкость схемы, чем у Avro, нет встроенного RPC (нужен gRPC).
- Сценарии использования: микросервисы, определения и описания API, мобильные бэкенды.
Apache Thrift
Лучше всего подходит для полных RPC-фреймворков, охватывающих несколько языков программирования.
- Преимущества: встроенная поддержка RPC, несколько протоколов, комплексное решение.
- Ограничения: более сложный, чем другие протоколы.
- Идеальные сценарии: мультиязычные сервисные архитектуры, кросс-языковые RPC.
Apache Parquet
Лучше всего подходит для аналитических рабочих нагрузок с колоночно-ориентированными шаблонами доступа.
- Преимущества: столбцовое хранение, отличное сжатие.
- Ограничения: не подходит для доступа к отдельным записям, аналитический фокус.
- Сценарии использования: хранилища данных, обработка в Spark/Hadoop, озера данных.
1. Шаблоны доступа: колоночные или строчные.
2. Потребности в эволюции: как часто ваши структуры данных будут меняться.
3. Языковые требования: какие языки программирования вам необходимо поддерживать.
4. Безопасность типов: насколько важна строгая типизация для вашего случая использования.
Говоря про Parquet, мы не рассмотрели такой формат для аналитики, как ORC (Optimized Row Columnar), но он используется по большей части в экосистеме Hadoop и является более узкоспециализированным.
Дополнительные материалы
- Обсуждение использования Parquet в Prometheus - https://docs.google.com/document/d/1dutHwZXibnq3_gIeMLMZh9uFkWToQ2TwazdoqFJzlEs/edit?tab=t.0#heading=h.6tqrdajo7je9
- Apache Thrift - https://thrift.apache.org/docs/
- Apache Avro - https://avro.apache.org/docs/
- Protobuf - https://protobuf.dev/
- Apache Parquet - https://parquet.apache.org/docs/
- MessagePack - https://msgpack.org/
- Статья про форматы файлов и данных - https://habr.com/ru/companies/vk/articles/741702/
- Книга - Designing Data-Intensive Applications by Martin Kleppmann - https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/ (в декабре 2025 года планируется выход 2 издания этой книги https://www.oreilly.com/library/view/designing-data-intensive-applications/9781098119058/)