62
48

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Avroについて調べてみた

Last updated at Posted at 2019-01-06

Apache Avroについて調べてみました。よくわからないところも多いので、指摘などがあればぜひコメントお願いします。

1. 概要

Avroは、スキーマ定義とバイナリでのエンコーディングを特徴とする、システム間でデータ交換を行うためのフォーマット。JSONでは型がなく文字列ベースで効率が悪くて困るような場合に使うもの。似たようなものとしては、Protocol BuffersMessage Packなどがある。

主に、ファイル形式、RPC用のプロトコル定義、Kafkaなどのメッセージ形式として使われる。以下では、RPCに関しては(よくわからないので)触れない。

日本語では、Apache Avro vs Protocol Buffersの資料がAvroの概要とProtocol Buffersとの違いがまとまっていてわかりやすい。

C, C++, C#, Java, PHP, Python, Ruby については公式のライブラリが用意されているが、(特に新し目の機能は)言語によって対応度合いが若干違うように見える。Goは、linkedin/goavroがよく使われていると思われる。以下の説明はJavaをベースにしている。

2. 主要な機能

2.1 スキーマ定義

スキーマはavscファイルで定義する。以下のデータ型が用意されていて、組み合わせてフィールドを定義する。若干古いが、Oracle NoSQL Databaseスタート・ガイドの第7章 Avroスキーマに日本語のドキュメントがあるので参考になる。

種類 データ型
Primitive Types null, boolean, int, long, float, double, bytes, string
Complex Types record, enum, array, maps, union, fixed
Logical Types Decimal, Date, Time, Timestamp, Duration

Logical Typeは、物理形式としてはPrimitive Typeを使ってシリアライズされる派生型。

スキーマは、JSON形式で記述する以外に、IDLから作成する方法もある。IDLを使うと、importなどの機能を使うことができる。

2.1.1 スキーマの例

(http://avro.apache.org/docs/current/spec.html より)

{"namespace": "example.avro",
 "type": "record",
 "name": "User",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": ["int", "null"]},
     {"name": "favorite_color", "type": ["string", "null"]}
 ]

2.1.2 IDLによるスキーマ定義の例

(https://mingqin.wordpress.com/2015/01/30/avro-idl-composites-avro-schemas-by-avrohubtool/ より)

@namespace("avro.examples.baseball")
protocol Baseball {
   import schema "name.avsc";
   import schema "coache.avsc";
   import schema "position.avsc";
   import schema "player.avsc";
   
   record Team {
       Player player;
       Coache  coache;
  }
}

2.1.3 Schema evolution

Avroでは、互換性のルールがあり、スキーマの変更時に互換性を維持できるようになっている。ただ、公式の仕様はわかりにくいので、viniciusccarvalho/schema-evolution-samplesの説明・例や、Confluent Platformの各コンポーネントの特徴 のほうがわかりやすい。

|互換性の種類|説明|
|---|---|---|
|前方互換|新しいスキーマで作られたデータを古いスキーマで読む|
|後方互換|古いスキーマで作成されたデータを新しいスキーマで読む|

前方互換性を維持するためには、スキーマへのカラム追加時にデフォルト値を指定する必要がある。

2.2 データ形式

Avroで用意されているデータ形式は3種類あり、用途に合わせて選択する。データの読み書きにはスキーマが必要になるため、ヘッダによるオーバーヘッドとスキーマの運用を考慮して決める必要がある。

種類 内容 説明 スキーマの運用
Binary Encoding バイナリのデータのみ、ヘッダなし BinaryEncoderを使う。単純なエンコーディングとしてのみ使用する場合 ディレクトリやトピックとスキーマを規約で対応付けておく。スキーマ更新時は全体で同期をとって対応が必要
Object Container Files ヘッダにスキーマ定義を含む DataFileWriterを使う。ファイルでのデータ交換用 埋め込まれているスキーマをそのまま利用可能
Single-Object Encoding ヘッダにスキーマのフィンガープリントを含む BinaryMessageEncoderを使う。Kafkaなどのメッセージング用 フィンガープリントを使用してスキーマを解決する

Object Container Files形式は、deflate/snappy圧縮も可能。また、BigQuery、RedShift、Sparkなどでサポートされている。Amazon EMR の Avro フォーマットのデータを Amazon Redshift にロードするも参照。

メッセージ用途には、Object Container Files形式はオーバーヘッドが大きいので、軽量な形式としてSingle-Object Encodingが用意されているが、自前でスキーマのバージョンなどを埋め込んで解決してもよい。

動的にスキーマを解決する仕組みとしては、大掛かりになるがConfluent Schema Registryもある。Confluent Platformの各コンポーネントの特徴も参照。

2.3 シリアライズに使用される主要なクラス

基本的には、DatumWriterのいずれかのサブクラスと、EncoderもしくはFileWriterを使用してシリアライズする。シリアライズのサンプルはGetting Started (Java)を参照。デシリアライズでは、対応するReader/Decoderを使用する。

こちらも若干古いが、Oracle NoSQL Databaseスタート・ガイドの第8章 Avroバインディングに日本語のドキュメントがある。

package class/Interface 説明
org.apache.avro.io DatumWriter(IF) スキーマに従ってインスタンスをEncoderに書き出す
org.apache.avro.io SpecificDatumWriter スキーマから自動生成されたクラスを使用してシリアライズ
org.apache.avro.io GenericDatumWriter クラスの自動生成を使わずにシリアライズする
org.apache.avro.io ReflectDatumWriter 既存のクラスをシリアライズする
org.apache.avro.io Encoder(IF) フィールドの値をシリアライズする
org.apache.avro.io BinaryEncoder フィールドの値をバイナリエンコーディングする
org.apache.avro.file DataFileWriter DatumWriterをObject Container Files形式のファイルに出力する(encoder不要)
org.apache.avro.message MessageEncoder(IF) ByteBuffer, OutputStreamに出力する
org.apache.avro.message BinaryMessageEncoder Single Object EncodingでByteBuffer, OutputStreamに出力する

PythonやRubyではクラス生成はサポートされていない(というか必要がない)ので、GenericDatumWriter相当のみとなる。Getting Started (Python)や、Avro in Rubyも参照。

Schema Evolutionを考えると、SpecificDatumWriterを使用する場合、自動生成されたクラスをどうバージョン管理するかが少し悩ましい気がする。

Appendix

62
48
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
62
48

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?