4.

Avro (.avro) | Apache Avro 行指向シリアライゼーション解説

編集
この記事の要点
  • Avro は Apache の行指向(row-based)バイナリデータ形式
  • JSON でスキーマを定義し、本体はコンパクトなバイナリ。スキーマもファイルに埋め込まれる
  • Kafka エコシステム標準 — Confluent Schema Registry と組み合わせるのが定番
  • スキーマ進化(reader/writer スキーマ)に強く、ニュースキーマで旧データも読める
  • 言語非依存(Java/Python/Go/C++/Ruby 等の公式バインディング)

要点

  • Apache Avro は Hadoop プロジェクト発祥の行指向(Row-oriented)バイナリシリアライゼーション形式で、拡張子は .avro
  • スキーマを JSON で定義し、本体はバイナリで持つ。スキーマがファイル先頭に同梱されるため、自己記述的(self-describing)。
  • スキーマ進化(Schema Evolution)に強く、フィールド追加・削除・型互換変更を後方互換で扱える設計が組み込まれている。
  • Apache Kafka のメッセージシリアライザの事実上の標準で、Confluent Schema Registry と組み合わせて使われる。

概要

Avro は 2009 年に Hadoop の作者 Doug Cutting らが「Hadoop の RPC とデータ保存を統一する」目的で立ち上げた OSS である。当時 Thrift や Protocol Buffers(Protocol Buffers)が同種の枠組みとして存在していたが、Avro はそれらが「コード生成必須」「タグ番号必須」だったのに対し、スキーマだけあれば動的に読み書きできる(コード生成は任意)という設計を採った点が大きな違いになっている。

用途としては大きく 2 系統あり、ひとつは バッチ系: Hadoop / Hive / Spark で長期保管するレコードを Avro 形式で書き出し、後から SQL で集計する。もうひとつは ストリーミング系: Kafka に流れるメッセージの 1 レコードを Avro でエンコードし、Schema Registry で型を共有する。とくに Kafka 連携での存在感が大きく、現代の Avro 利用の主戦場はこちらに移っている。

Parquet/ORC が「列指向で集計に強い」のとは対照的に、Avro は行指向で書き込み・追記・1 行単位の取り出しが速い。アクセスパターンが「直近の 1 件を取りたい」「ストリームで流れてくる」場合は Avro、「数億行を列で舐めて集計したい」場合は Parquet という棲み分けになる。

内部構造

Avro ファイル(Object Container File)は次のレイアウトを持つ。

  1. ヘッダ: マジックバイト Obj\1、メタデータ(スキーマ JSON、圧縮コーデック)、16 バイトのシンクマーカ。
  2. データブロック: 複数レコードをまとめたブロック。先頭にレコード数、バイト数、その後にバイナリ本体、最後に再度シンクマーカ。
  3. シンクマーカは破損時の再同期点として機能し、Hadoop の InputSplit 境界としても使われる。

スキーマは JSON で表現される。例:

{
  "type": "record",
  "name": "User",
  "fields": [
    { "name": "id",    "type": "long" },
    { "name": "name",  "type": "string" },
    { "name": "email", "type": ["null", "string"], "default": null }
  ]
}

["null", "string"] のような Union 型で nullable を表す。バイナリ本体はタグ番号を持たず、スキーマ順にそのまま並べていく 位置型(positional) エンコーディングのため、Protocol Buffers よりさらに小さくなることが多い。その代わり、スキーマが無いと 1 バイトも復号できない。

主な用途

  • Kafka + Schema Registry: Producer/Consumer 間でスキーマを共有し、互換性ルール(BACKWARD/FORWARD/FULL)を自動チェック。プロダクション Kafka では半ば必須。
  • Hadoop/Hive のレコード保存: 1 件 1 件追記する性質のログ(クリックストリーム、アクセスログ)に向く。
  • RPC のメッセージ: Hadoop の HDFS/YARN 内部通信などで利用。
  • 長期アーカイブ: スキーマがファイルに同梱されるため、数年後でもスキーマ別管理不要で読める。

関連形式との比較

形式方向スキーマ得意
AvroJSON、ファイル同梱Kafka / ストリーミング / スキーマ進化
Protocol Buffers.proto、別管理gRPC / アプリ間通信
Parquetファイル内OLAP / 大規模集計
JSON行(テキスト)Web API

Protocol Buffers と用途は似るが、Protobuf が「クライアント/サーバ間の RPC ペイロード」に振った設計であるのに対し、Avro は「ファイルとして長期保管しても自己記述で読めること」に振っている点で住み分けがある。

コマンド・ツール

公式 CLI は avro-tools で、Apache Avro のリリース jar として配布される。

$ java -jar avro-tools-1.11.3.jar getschema user.avro
$ java -jar avro-tools-1.11.3.jar tojson user.avro | head
$ java -jar avro-tools-1.11.3.jar fromjson --schema-file user.avsc input.json > user.avro

Python では fastavro が標準的に使われる。

import fastavro
with open("user.avro", "rb") as f:
    reader = fastavro.reader(f)
    for record in reader:
        print(record)

Kafka 連携では、Confluent の Python/Java クライアントに含まれる AvroSerializer / AvroDeserializer 経由で読み書きするのが普通で、レコード単体(ファイルヘッダなし)のワイヤフォーマットになる。

注意点

  • スキーマが無いと読めない: ファイル形式ならヘッダ同梱だが、Kafka の素のメッセージはスキーマを別チャネル(Schema Registry)で配ることが前提。
  • 列指向ではない: 「数億行 × 数十列のうち 2 列だけ集計」は遅い。集計用には Parquet/ORC に変換する。
  • Union 型の扱いに注意: ["null","string"] の順序が違うとデフォルト値の意味が変わる。互換性ルールで「最初の型をデフォルト型として扱う」と決まっている。
  • JSON エンコーディングは大きい: avro-tools tojson は人間用のデバッグ表示で、容量は CSV 並みかそれ以上に膨らむ。本番運用ではバイナリ前提。

関連リンク

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. SQL ダンプ(.sql)
  2. SQLite(.sqlite / .sqlite3 / .db)
  3. Parquet(.parquet)
  4. Avro(.avro)
  5. ORC(.orc)
  6. NDJSON / JSONL(.ndjson / .jsonl)
  7. BSON(.bson)
  8. Protocol Buffers(.proto)
  9. Feather / Arrow IPC(.feather / .ipc / .arrow)
  10. DB ダンプ(.dump / .bak)

最近更新/作成されたページ