#概要
Apache Avroにはデータ・スキーマを用いて永続化や通信を行うデータを圧縮する為の仕様「A compact, fast, binary data format.(コンパクトで高速なバイナリ形式データ)」があります。
本記事ではAvroの詳細まで言及しませんが、この仕様をGolangで実装して圧縮されたデータを実感してみたいと思います。
#データ圧縮の準備
###Avroスキーマ
Avroバイナリデータに圧縮するには、予めデータ構造のスキーマ定義を作成する必要があります。
まずは2つの項目を持つ簡単なスキーマを定義します。
(後ほどGolangのソースコード内でstringデータとして使用します)
{
"namespace": "TestSchema",
"type": "record",
"name": "TestData",
"fields" : [
{ "name" : "id", "type" : "int" }, { "name" : "value", "type" : "string" }
]
}
###圧縮前のデータ(JSON)
スキーマにはint型の"id"と言う名前の項目とstring型の"value"と言う2つの項目が定義されています。
この定義に沿った以下のJSONデータを作成します。
{"id":10001,"value":"test_value"}
#データ圧縮ロジック
###Goライブラリ
以下のコマンドを実行してライブラリを取得します。
go get "github.com/linkedin/goavro"
##シリアライズ処理手順
以下の手順で実行します。
// 1.JSON文字列をGolangのプリミティブ型のデータへ変換
// 1-1.スキーマを設定したCodecを生成
codec, _ := goavro.NewCodec(`
{
"namespace": "TestSchema",
"type": "record",
"name": "TestData",
"fields" : [
{ "name" : "id", "type" : "int" }, { "name" : "value", "type" : "string" }
]
}`)
// 1-2.JSON文字列をGoデータへ変換
textual := []byte(`{"id":10001,"value":"test_value"}`)
native, _, err := codec.NativeFromTextual(textual) // nativeはmap[string]interface{}型
if err != nil {
panic(err)
}
log.Printf("textual length:[%d]\n", len(textual))
// 2.GoデータをAvroバイナリへシリアライズ
binary, err := codec.BinaryFromNative(nil, native) // binaryは[]byte型
if err != nil {
panic(err)
}
log.Printf("binary length:[%d]\n", len(binary))
###処理結果
元のJSON文字列33バイトから、バイナリデータ変換後は14バイトまで圧縮されています。
textual length:[33]
binary length:[14]
##デシリアライズ処理手順
以下の手順で実行します。
Codecはシリアライズと同じものを使用できます。
// 3.AvroバイナリデータをGoデータへデシリアライズ
native, _, err := codec.NativeFromBinary(binary)
if err != nil {
panic(err)
}
log.Printf("Deserialized:%v\n", native)
// 4.JSON文字列に戻すことも可能
textual, err := codec.TextualFromNative(nil, native)
if err != nil {
panic(err)
}
log.Printf("JSON string :%v\n", string(textual))
###処理結果
バイナリから復元されたデータはmap[string]interface{}型に変換されます。
Deserialized:map[id:10001 value:test_value]
JSON string :{"value":"test_value","id":10001}
###どの辺がポイント?
・データ構造の情報を持たない
シリアライズにもデシリアライズにもスキーマ定義が必要で、その管理も必要になりますが、スキーマに書かれている情報を持つ必要が無いのでデータは小さくなります。
永続化にも通信にも有用です。
取り急ぎGolangでAvroのデータを扱いたい時は上記ソースコードをコピペして、スキーマ定義とJSON文字列を適切な値へ置換してください。(エラー処理の実装も忘れずに)
#Appendix
*Apache Avro公式ページ
*linkedin/goavro(Github)