Avro-quick-guide
AVRO-概要
ネットワークを介して、またはその永続ストレージのためにデータを転送するには、データをシリアル化する必要があります。 JavaとHadoopが提供する*シリアライゼーションAPI の前に、スキーマベースのシリアライゼーションテクニックである *Avro と呼ばれる特別なユーティリティがあります。
このチュートリアルでは、Avroを使用してデータをシリアル化および逆シリアル化する方法を学習します。 Avroは、さまざまなプログラミング言語用のライブラリを提供しています。 このチュートリアルでは、Javaライブラリを使用した例を示します。
Avroとは何ですか?
Apache Avroは、言語に依存しないデータシリアル化システムです。 Hadoopの父であるDoug Cuttingによって開発されました。 Hadoopの書き込み可能なクラスには言語の移植性がないため、Avroは複数の言語で処理できるデータ形式を扱うため、非常に役立ちます。 Avroは、Hadoopでデータをシリアル化するための推奨ツールです。
Avroにはスキーマベースのシステムがあります。 言語に依存しないスキーマは、読み取りおよび書き込み操作に関連付けられています。 Avroは、スキーマが組み込まれたデータをシリアル化します。 Avroは、データをコンパクトなバイナリ形式にシリアル化します。これは、任意のアプリケーションで逆シリアル化できます。
AvroはJSON形式を使用してデータ構造を宣言します。 現在、Java、C、C ++、C#、Python、Rubyなどの言語をサポートしています。
Avroスキーマ
Avroは*スキーマ*に大きく依存しています。 これにより、スキーマに関する予備知識がなくても、すべてのデータを書き込むことができます。 高速にシリアル化され、結果としてシリアル化されたデータのサイズが小さくなります。 スキーマは、さらに処理するためにAvroデータとともにファイルに保存されます。
RPCでは、クライアントとサーバーは接続中にスキーマを交換します。 この交換は、同じ名前のフィールド、欠落フィールド、追加フィールドなどの間の通信に役立ちます。
AvroスキーマはJSONで定義されているため、JSONライブラリを使用した言語での実装が簡素化されます。
Avroのように、Hadoopには、 Sequence Files、Protocol Buffers 、 Thrift などの他のシリアル化メカニズムがあります。
ThriftおよびProtocolバッファーとの比較
*Thrift* および *Protocol Buffers* は、Avroで最も優れたライブラリです。 Avroは、次の点でこれらのフレームワークとは異なります-
- Avroは、要件に従って動的タイプと静的タイプの両方をサポートしています。 プロトコルバッファとThriftは、インターフェイス定義言語(IDL)を使用してスキーマとそのタイプを指定します。 これらのIDLは、シリアル化および逆シリアル化のためのコードを生成するために使用されます。
- AvroはHadoopエコシステムに組み込まれています。 ThriftおよびProtocol Buffersは、Hadoopエコシステムに組み込まれていません。
ThriftおよびProtocol Bufferとは異なり、Avroのスキーマ定義はJSONであり、独自のIDLではありません。
Property | Avro | Thrift & Protocol Buffer |
---|---|---|
Dynamic schema | Yes | No |
Built into Hadoop | Yes | No |
Schema in JSON | Yes | No |
No need to compile | Yes | No |
No need to declare IDs | Yes | No |
Bleeding edge | Yes | No |
Avroの機能
以下は、Avroの顕著な特徴の一部です-
- Avroは、言語に依存しない*データシリアル化システムです。
- 多くの言語(現在はC、C ++、C#、Java、Python、Ruby)で処理できます。
- Avroは、*圧縮可能*および*分割可能*の両方であるバイナリ構造化形式を作成します。 したがって、Hadoop MapReduceジョブへの入力として効率的に使用できます。
- Avroは、*豊富なデータ構造*を提供します。 たとえば、配列、列挙型、およびサブレコードを含むレコードを作成できます。 これらのデータ型は任意の言語で作成でき、Hadoopで処理でき、結果を第3言語にフィードできます。
- JSON で定義されているAvro schemas は、JSONライブラリをすでに持っている言語での実装を容易にします。
- Avroは、_Avro Data File、_という名前の自己記述型ファイルを作成します。このファイルには、メタデータセクションにスキーマとともにデータが格納されます。
- Avroは、リモートプロシージャコール(RPC)でも使用されます。 RPC中に、クライアントとサーバーは接続ハンドシェイクでスキーマを交換します。
Avroの一般的な作業
Avroを使用するには、所定のワークフローに従う必要があります-
- *ステップ1 *-スキーマを作成します。 ここでは、データに従ってAvroスキーマを設計する必要があります。
- *ステップ2 *-スキーマをプログラムに読み込みます。 それは2つの方法で行われます-
- スキーマに対応するクラスを生成する-Avroを使用してスキーマをコンパイルします。 これにより、スキーマに対応するクラスファイルが生成されます
- パーサーライブラリを使用して-パーサーライブラリを使用してスキーマを直接読み取ることができます。
- *ステップ3 *-*パッケージorg.apache.avro.specific *にあるAvroに提供されているシリアル化APIを使用してデータをシリアル化します。
- ステップ4 *-Avroに提供されているデシリアライゼーションAPIを使用してデータをデシリアライズします。これは package org.apache.avro.specific。*にあります
AVRO-シリアル化
データは2つの目的のためにシリアル化されています-
- 永続ストレージ用
- ネットワーク経由でデータを転送するには
シリアル化とは何ですか?
シリアル化は、データ構造またはオブジェクトの状態をバイナリ形式またはテキスト形式に変換して、ネットワークを介してデータを転送したり、永続ストレージに保存したりするプロセスです。 データがネットワーク経由で転送されるか、永続ストレージから取得されると、データを再度シリアル化解除する必要があります。 直列化は marshalling と呼ばれ、逆直列化は unmarshalling と呼ばれます。
Javaでのシリアル化
Javaは object serialization と呼ばれるメカニズムを提供します。オブジェクトは、オブジェクトのデータと、オブジェクトのタイプおよびオブジェクトに格納されているデータのタイプに関する情報を含むバイトシーケンスとして表すことができます。
シリアル化されたオブジェクトは、ファイルに書き込まれた後、ファイルから読み取り、逆シリアル化できます。 つまり、オブジェクトとそのデータを表す型情報とバイトを使用して、メモリ内でオブジェクトを再作成できます。
*ObjectInputStream* および *ObjectOutputStream* クラスは、それぞれJavaでオブジェクトをシリアライズおよびデシリアライズするために使用されます。
Hadoopでのシリアル化
一般的に、Hadoopのような分散システムでは、シリアル化の概念は*プロセス間通信*および*永続ストレージ*に使用されます。
プロセス間通信
- ネットワークに接続されたノード間のプロセス間通信を確立するために、RPC手法が使用されました。
- RPCは内部シリアル化を使用して、ネットワーク経由でリモートノードに送信する前にメッセージをバイナリ形式に変換しました。 一方、リモートシステムはバイナリストリームを元のメッセージに逆シリアル化します。
- RPCのシリアル化形式は次のようにする必要があります-
- コンパクト-データセンターで最も少ないリソースであるネットワーク帯域幅を最大限に活用します。
- 高速-ノード間の通信は分散システムで非常に重要であるため、シリアル化と逆シリアル化のプロセスは高速で、オーバーヘッドが少なくなります。
- 拡張可能-新しい要件を満たすためにプロトコルは時間とともに変化するため、クライアントとサーバーに対して制御された方法でプロトコルを進化させることは簡単です。
- 相互運用可能-メッセージ形式は、異なる言語で記述されたノードをサポートする必要があります。
永続的ストレージ
永続ストレージは、電源が失われてもデータを失わないデジタルストレージ施設です。 ファイル、フォルダー、データベースは永続ストレージの例です。
書き込み可能なインターフェース
これは、シリアル化および逆シリアル化のメソッドを提供するHadoopのインターフェイスです。 次の表はメソッドを説明しています-
S.No. | Methods and Description |
---|---|
1 |
void readFields(DataInput in) このメソッドは、指定されたオブジェクトのフィールドを逆シリアル化するために使用されます。 |
2 |
void write(DataOutput out) このメソッドは、指定されたオブジェクトのフィールドをシリアル化するために使用されます。 |
書き込み可能な比較可能なインターフェース
*Writable* および *Comparable* インターフェースの組み合わせです。 このインターフェースは、Hadoopの *Writable* インターフェースとJavaの *Comparable* インターフェースを継承します。 したがって、データのシリアル化、逆シリアル化、および比較のためのメソッドを提供します。
S.No. | Methods and Description |
---|---|
1 |
int compareTo(class obj) このメソッドは、現在のオブジェクトを指定されたオブジェクトobjと比較します。 |
これらのクラスに加えて、HadoopはWritableComparableインターフェースを実装する多くのラッパークラスをサポートしています。 各クラスはJavaプリミティブ型をラップします。 Hadoopのシリアル化のクラス階層は以下のとおりです-
Hadoop Serialization Hierarchy
これらのクラスは、Hadoopでさまざまなタイプのデータをシリアル化するのに役立ちます。 たとえば、 IntWritable クラスを考えてみましょう。 このクラスを使用して、Hadoopのデータをシリアライズおよびデシリアライズする方法を見てみましょう。
IntWritableクラス
このクラスは、 Writable、Comparable 、および WritableComparable インターフェイスを実装します。 整数データ型をラップします。 このクラスは、整数型のデータをシリアライズおよびデシリアライズするために使用されるメソッドを提供します。
コンストラクタ
S.No. | Summary |
---|---|
1 | IntWritable() |
2 | IntWritable( int value) |
方法
S.No. | Summary |
---|---|
1 |
int get() このメソッドを使用すると、現在のオブジェクトに存在する整数値を取得できます。 |
2 |
void readFields(DataInput in) このメソッドは、指定された DataInput オブジェクトのデータを逆シリアル化するために使用されます。 |
3 |
void set(int value) このメソッドは、現在の IntWritable オブジェクトの値を設定するために使用されます。 |
4 |
void write(DataOutput out) このメソッドは、現在のオブジェクトのデータを指定された DataOutput オブジェクトにシリアル化するために使用されます。 |
Hadoopでのデータのシリアル化
整数型のデータをシリアル化する手順を以下に説明します。
- 整数値をラップすることにより、 IntWritable クラスをインスタンス化します。
- ByteArrayOutputStream クラスをインスタンス化します。
- DataOutputStream クラスをインスタンス化し、 ByteArrayOutputStream クラスのオブジェクトをそれに渡します。
- * write()*メソッドを使用して、IntWritableオブジェクトの整数値をシリアル化します。 このメソッドには、DataOutputStreamクラスのオブジェクトが必要です。
- シリアル化されたデータは、インスタンス化時に DataOutputStream クラスにパラメーターとして渡されるバイト配列オブジェクトに保存されます。 オブジェクト内のデータをバイト配列に変換します。
例
次の例は、Hadoopで整数型のデータをシリアル化する方法を示しています-
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
public class Serialization {
public byte[] serialize() throws IOException{
//Instantiating the IntWritable object
IntWritable intwritable = new IntWritable(12);
//Instantiating ByteArrayOutputStream object
ByteArrayOutputStream byteoutputStream = new ByteArrayOutputStream();
//Instantiating DataOutputStream object
DataOutputStream dataOutputStream = new
DataOutputStream(byteoutputStream);
//Serializing the data
intwritable.write(dataOutputStream);
//storing the serialized object in bytearray
byte[] byteArray = byteoutputStream.toByteArray();
//Closing the OutputStream
dataOutputStream.close();
return(byteArray);
}
public static void main(String args[]) throws IOException{
Serialization serialization= new Serialization();
serialization.serialize();
System.out.println();
}
}
Hadoopでのデータの逆シリアル化
データの整数型をデシリアライズする手順については、以下で説明します-
- 整数値をラップすることにより、 IntWritable クラスをインスタンス化します。
- ByteArrayOutputStream クラスをインスタンス化します。
- DataOutputStream クラスをインスタンス化し、 ByteArrayOutputStream クラスのオブジェクトをそれに渡します。
- IntWritableクラスの* readFields()メソッドを使用して、 *DataInputStream のオブジェクトのデータを逆シリアル化します。
- デシリアライズされたデータは、IntWritableクラスのオブジェクトに保存されます。 このデータを取得するには、このクラスの* get()*メソッドを使用します。
例
次の例は、Hadoopで整数型のデータをデシリアライズする方法を示しています-
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import org.apache.hadoop.io.IntWritable;
public class Deserialization {
public void deserialize(byte[]byteArray) throws Exception{
//Instantiating the IntWritable class
IntWritable intwritable =new IntWritable();
//Instantiating ByteArrayInputStream object
ByteArrayInputStream InputStream = new ByteArrayInputStream(byteArray);
//Instantiating DataInputStream object
DataInputStream datainputstream=new DataInputStream(InputStream);
//deserializing the data in DataInputStream
intwritable.readFields(datainputstream);
//printing the serialized data
System.out.println((intwritable).get());
}
public static void main(String args[]) throws Exception {
Deserialization dese = new Deserialization();
dese.deserialize(new Serialization().serialize());
}
}
Javaシリアル化に対するHadoopの利点
HadoopのWritableベースのシリアル化は、Writableオブジェクトを再利用することでオブジェクト作成のオーバーヘッドを削減できますが、これはJavaのネイティブシリアル化フレームワークでは不可能です。
Hadoopシリアル化の欠点
Hadoopデータをシリアル化するには、2つの方法があります-
- Hadoopのネイティブライブラリが提供する Writable クラスを使用できます。
- データをバイナリ形式で保存する Sequence Files を使用することもできます。
これら2つのメカニズムの主な欠点は、 Writables および SequenceFiles にはJava APIしかなく、他の言語での書き込みまたは読み取りができないことです。
したがって、上記の2つのメカニズムを使用してHadoopで作成されたファイルは、他の第3言語で読み取ることができません。これにより、Hadoopは制限付きボックスになります。 この欠点に対処するために、Doug Cuttingは Avro を作成しました。これは*言語に依存しないデータ構造*です。
AVRO-環境設定
Apacheソフトウェア基盤は、Avroにさまざまなリリースを提供します。 Apacheミラーから必要なリリースをダウンロードできます。 私たちは、Avroで動作するように環境を設定する方法を見てみましょう-
Avroのダウンロード
Apache Avroをダウンロードするには、次の手順に進みます-
- Webページhttp://avro.apache.org/.[Apache.org]を開きます。 以下に示すように、Apache Avroのホームページが表示されます-
- プロジェクト→リリースをクリックします。 リリースのリストを取得します。
- ダウンロードリンクに移動する最新リリースを選択します。
- mirror.nexcessは、以下に示すようにAvroがサポートするさまざまな言語のすべてのライブラリのリストを見つけることができるリンクの1つです-
提供されている任意の言語のライブラリを選択してダウンロードできます。 このチュートリアルでは、Javaを使用します。 したがって、jarファイル avro-1.7.7.jar および avro-tools-1.7.7.jar をダウンロードします。
Eclipseを使用するAvro
Eclipse環境でAvroを使用するには、以下の手順に従う必要があります-
- *ステップ1. * Eclipseを開きます。
- *ステップ2. *プロジェクトを作成します。
- *ステップ3. *プロジェクト名を右クリックします。 ショートカットメニューが表示されます。
- *ステップ4. * [ビルドパス]をクリックします。 別のショートカットメニューに移動します。
- *ステップ5. * [ビルドパスの構成…]をクリックします。*以下に示すように、プロジェクトの[プロパティ]ウィンドウが表示されます-
- *ステップ6. * [ライブラリ]タブで、[*外部JARを追加…]ボタンをクリックします。
- ステップ7. *ダウンロードしたjarファイル *avro-1.77.jar を選択します。
- ステップ8. * *OK をクリックします。
Mavenを使用したAvro
Mavenを使用してAvroライブラリをプロジェクトに取り込むこともできます。 以下に、Avroのpom.xmlファイルを示します。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Test</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro-tools</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.0-beta9</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.0-beta9</version>
</dependency>
</dependencies>
</project>
クラスパスの設定
Linux環境でAvroを使用するには、次のjarファイルをダウンロードします-
- avro-1.77.jar
- avro-tools-1.77.jar
- log4j-api-2.0-beta9.jar
- og4j-core-2.0.beta9.jar。
以下に示すように、これらのファイルをフォルダーにコピーし、クラスパスを。 /bashrc ファイルでフォルダーに設定します。
#class path for Avro
export CLASSPATH=$CLASSPATH://home/Hadoop/Avro_Work/jars/*
AVRO-スキーマ
スキーマベースのシリアル化ユーティリティであるAvroは、スキーマを入力として受け入れます。 さまざまなスキーマが利用可能であるにもかかわらず、Avroはスキーマを定義する独自の標準に従います。 これらのスキーマは、次の詳細を説明します-
- ファイルのタイプ(デフォルトで記録)
- 記録の場所
- レコードの名前
- 対応するデータ型を持つレコードのフィールド
これらのスキーマを使用すると、シリアル化された値を少ないスペースでバイナリ形式で保存できます。 これらの値は、メタデータなしで保存されます。
Avroスキーマの作成
Avroスキーマは、JavaScript Object Notation(JSON)ドキュメント形式で作成されます。これは、軽量のテキストベースのデータ交換形式です。 次のいずれかの方法で作成されます-
- JSON文字列
- JSONオブジェクト
- JSON配列
例-次の例は、名前空間finddevguidesで、名前Employeeの名前と年齢のフィールドを持つドキュメントを定義するスキーマを示しています。
{
"type" : "record",
"namespace" : "finddevguides",
"name" : "Employee",
"fields" : [
{ "name" : "Name" , "type" : "string" },
{ "name" : "Age" , "type" : "int" }
]
}
この例では、各レコードに4つのフィールドがあることがわかります-
- type -このフィールドはドキュメントの下にあり、fieldsという名前のフィールドの下にもあります。
- ドキュメントの場合、複数のフィールドがあるため、ドキュメントのタイプ、通常はレコードを示します。
- フィールドの場合、タイプはデータタイプを表します。
- namespace -このフィールドは、オブジェクトが存在する名前空間の名前を記述します。
- name -このフィールドは、fieldsという名前のフィールドの下だけでなく、ドキュメントの下にもあります。
- ドキュメントの場合、スキーマ名を記述します。 このスキーマ名と名前空間は、ストア内のスキーマを一意に識別します( Namespace.schema name )。 上記の例では、スキーマの完全な名前はfinddevguides.Employeeになります。
- フィールドの場合、フィールドの名前を記述します。
Avroのプリミティブデータ型
Avroスキーマには、プリミティブデータ型と複雑なデータ型があります。 次の表では、Avroの*プリミティブデータ型*について説明します-
Data type | Description |
---|---|
null | Null is a type having no value. |
int | 32-bit signed integer. |
long | 64-bit signed integer. |
float | single precision (32-bit) IEEE 754 floating-point number. |
double | double precision (64-bit) IEEE 754 floating-point number. |
bytes | sequence of 8-bit unsigned bytes. |
string | Unicode character sequence. |
Avroの複雑なデータ型
プリミティブデータ型に加えて、Avroは6つの複雑なデータ型、つまりレコード、列挙、配列、マップ、ユニオン、固定を提供します。
記録
Avroのレコードデータタイプは、複数の属性のコレクションです。 それは次の属性をサポートしています-
- name -このフィールドの値は、レコードの名前を保持します。
- namespace -このフィールドの値は、名前空間の名前を保持します オブジェクトが保存されます。
- type -この属性の値は、ドキュメント(レコード)のタイプまたはスキーマ内のフィールドのデータタイプを保持します。
- fields -このフィールドはJSON配列を保持します。JSON配列には、スキーマ内のすべてのフィールドのリストがあり、各フィールドには名前とタイプの属性があります。
例
以下にレコードの例を示します。
{
" type " : "record",
" namespace " : "finddevguides",
" name " : "Employee",
" fields " : [
{ "name" : " Name" , "type" : "string" },
{ "name" : "age" , "type" : "int" }
]
}
Enum
列挙はコレクション内のアイテムのリストであり、Avro列挙は次の属性をサポートしています-
- name -このフィールドの値は、列挙の名前を保持します。
- namespace -このフィールドの値には、列挙の名前を修飾する文字列が含まれています。
- symbols -このフィールドの値は、列挙型のシンボルを名前の配列として保持します。
例
以下に列挙の例を示します。
{
"type" : "enum",
"name" : "Numbers",
"namespace": "data",
"symbols" : [ "ONE", "TWO", "THREE", "FOUR" ]
}
配列
このデータ型は、単一の属性項目を持つ配列フィールドを定義します。 この項目属性は、配列内の項目のタイプを指定します。
例
{ " type " : " array ", " items " : " int " }
Maps
マップデータタイプはキーと値のペアの配列であり、データをキーと値のペアとして整理します。 Avroマップのキーは文字列でなければなりません。 マップの値は、マップのコンテンツのデータ型を保持します。
例
{"type" : "map", "values" : "int"}
組合
ユニオンデータ型は、フィールドに1つ以上のデータ型がある場合は常に使用されます。 JSON配列として表されます。 たとえば、フィールドがintまたはnullの場合、ユニオンは["int"、 "null"]として表されます。
例
以下は、共用体を使用したドキュメントの例です-
{
"type" : "record",
"namespace" : "finddevguides",
"name" : "empdetails ",
"fields" :
[
{ "name" : "experience", "type": ["int", "null"] }, { "name" : "age", "type": "int" }
]
}
一定
このデータ型は、バイナリデータの格納に使用できる固定サイズのフィールドを宣言するために使用されます。 属性としてフィールド名とデータがあります。 Nameはフィールドの名前を保持し、sizeはフィールドのサイズを保持します。
例
{ "type" : "fixed" , "name" : "bdata", "size" : 1048576}
AVRO-リファレンスAPI
前の章では、Avroの入力タイプ、つまりAvroスキーマについて説明しました。 この章では、Avroスキーマのシリアル化と逆シリアル化で使用されるクラスとメソッドについて説明します。
SpecificDatumWriterクラス
このクラスはパッケージ org.apache.avro.specific に属します。 Javaオブジェクトをメモリ内のシリアル化された形式に変換する DatumWriter インターフェイスを実装します。
コンストラクタ
S.No. | Description |
---|---|
1 | SpecificDatumWriter(Schema schema) |
方法
S.No. | Description |
---|---|
1 |
SpecificData getSpecificData() このライターが使用するSpecificData実装を返します。 |
SpecificDatumReaderクラス
このクラスはパッケージ org.apache.avro.specific に属します。 スキーマのデータを読み取り、メモリ内のデータ表現を決定する DatumReader インターフェイスを実装します。 SpecificDatumReader は、生成されたJavaクラスをサポートするクラスです。
コンストラクタ
S.No. | Description |
---|---|
1 |
SpecificDatumReader(Schema schema) ライターのスキーマとリーダーのスキーマが同じ場所に構築します。 |
方法
S.No. | Description |
---|---|
1 |
SpecificData getSpecificData() 含まれているSpecificDataを返します。 |
2 |
void setSchema(Schema actual) このメソッドは、ライターのスキーマを設定するために使用されます。 |
DataFileWriter
*emp* クラスの *DataFileWrite* をインスタンス化します。 このクラスは、スキーマに準拠したデータのシーケンスシリアル化されたレコードを、スキーマとともにファイルに書き込みます。
コンストラクタ
S.No. | Description |
---|---|
1 | DataFileWriter(DatumWriter<D> dout) |
方法
S.No | Description |
---|---|
1 |
void append(D datum) ファイルにデータを追加します。 |
2 |
DataFileWriter<D> appendTo(File file) このメソッドは、既存のファイルに追加するライターを開くために使用されます。 |
データファイルリーダー
このクラスは、 DataFileWriter で書き込まれたファイルへのランダムアクセスを提供します。 クラス DataFileStream を継承します。
コンストラクタ
S.No. | Description |
---|---|
1 | DataFileReader(File file, DatumReader<D> reader)) |
方法
S.No. | Description |
---|---|
1 |
next() ファイル内の次のデータを読み取ります。 |
2 |
Boolean hasNext() このファイルにさらにエントリが残っている場合はtrueを返します。 |
クラスSchema.parser
このクラスは、JSON形式のスキーマのパーサーです。 スキーマを解析するメソッドが含まれています。 org.apache.avro パッケージに属します。
コンストラクタ
S.No. | Description |
---|---|
1 | Schema.Parser() |
方法
S.No. | Description |
---|---|
1 |
parse (File file) 指定された file で提供されるスキーマを解析します。 |
2 |
parse (InputStream in) 指定された InputStream で提供されるスキーマを解析します。 |
3 |
parse (String s) 指定された String で提供されるスキーマを解析します。 |
インターフェースGenricRecord
このインターフェイスは、名前とインデックスでフィールドにアクセスするメソッドを提供します。
方法
S.No. | Description |
---|---|
1 |
Object get(String key) 指定されたフィールドの値を返します。 |
2 |
void put(String key, Object v) 名前を指定してフィールドの値を設定します。 |
クラスGenericData.Record
コンストラクタ
S.No. | Description |
---|---|
1 | GenericData.Record(Schema schema) |
方法
S.No. | Description |
---|---|
1 |
Object get(String key) 指定された名前のフィールドの値を返します。 |
2 |
Schema getSchema() このインスタンスのスキーマを返します。 |
3 |
void put(int i, Object v) スキーマ内での位置を指定して、フィールドの値を設定します。 |
4 |
void put(String key, Object value) 名前を指定してフィールドの値を設定します。 |
AVRO-生成クラスによるシリアル化
スキーマに対応するクラスを生成するか、パーサーライブラリを使用して、Avroスキーマをプログラムに読み込むことができます。 この章では、クラスを生成してスキーマを読み取る方法と、Avrを使用してデータを*シリアル化*する方法について説明します。
クラスの生成によるシリアル化
Avroを使用してデータをシリアル化するには、以下の手順に従ってください-
- Avroスキーマを記述します。
- Avroユーティリティを使用してスキーマをコンパイルします。 あなたはそれに対応するJavaコードを取得します スキーマ
- スキーマにデータを入力します。
- Avroライブラリを使用してシリアル化します。
スキーマの定義
あなたは次の詳細を持つスキーマが必要だと仮定します-
Field | Name | id | age | salary | address |
type | String | int | int | int | string |
以下に示すようにAvroスキーマを作成します。
*emp.avsc* として保存します。
{
"namespace": "finddevguides.com",
"type": "record",
"name": "emp",
"fields": [
{"name": "name", "type": "string"},
{"name": "id", "type": "int"},
{"name": "salary", "type": "int"},
{"name": "age", "type": "int"},
{"name": "address", "type": "string"}
]
}
スキーマのコンパイル
Avroスキーマを作成したら、Avroツールを使用して作成したスキーマをコンパイルする必要があります。 avro-tools-1.7.7.jar は、ツールを含むjarです。
Avroスキーマをコンパイルする構文
java -jar <path/to/avro-tools-1.7.7.jar> compile schema <path/to/schema-file> <destination-folder>
ホームフォルダーでターミナルを開きます。
以下に示すように、Avroで動作する新しいディレクトリを作成します-
$ mkdir Avro_Work
新しく作成されたディレクトリで、3つのサブディレクトリを作成します-
- 最初に* schema、*という名前を付けて、スキーマを配置します。
- 生成されたコードを配置するための* with_code_gen、*という名前。
- 3番目の名前は jars で、jarファイルを配置します。
$ mkdir schema
$ mkdir with_code_gen
$ mkdir jars
次のスクリーンショットは、すべてのディレクトリを作成した後の Avro_work フォルダーの外観を示しています。
- ここで、 /home/Hadoop/Avro_work/jars/avro-tools-1.7.7.jar は、avro-tools-1.7.7.jarファイルをダウンロードしたディレクトリのパスです。
- /home/Hadoop/Avro_work/schema/ は、スキーマファイルemp.avscが保存されているディレクトリのパスです。
- /home/Hadoop/Avro_work/with_code_gen は、生成されたクラスファイルを保存するディレクトリです。
次に、以下に示すようにスキーマをコンパイルします-
$ java -jar/home/Hadoop/Avro_work/jars/avro-tools-1.7.7.jar compile schema/home/Hadoop/Avro_work/schema/emp.avsc/home/Hadoop/Avro/with_code_gen
コンパイル後、スキーマの名前空間に応じたパッケージが宛先ディレクトリに作成されます。 このパッケージ内で、スキーマ名を持つJavaソースコードが作成されます。 この生成されたソースコードは、アプリケーションで直接使用できる特定のスキーマのJavaコードです。
たとえば、このインスタンスでは、 finddevguides という名前のパッケージ/フォルダーが作成され、comという名前の別のフォルダーが含まれます(名前空間はfinddevguides.comであるため)、その中に生成されたファイル emp.java を確認できます。 次のスナップショットは emp.java を示しています-
このクラスは、スキーマに従ってデータを作成するのに役立ちます。
生成されたクラスが含まれています-
- デフォルトのコンストラクター、およびスキーマのすべての変数を受け入れるパラメーター化されたコンストラクター。
- スキーマ内のすべての変数の設定メソッドと取得メソッド。
- スキーマを返すGet()メソッド。
- ビルダーメソッド。
データの作成とシリアル化
まず、このプロジェクトで使用される生成されたJavaファイルを現在のディレクトリにコピーするか、それが置かれている場所からインポートします。
これで、新しいJavaファイルを作成し、生成されたファイル( emp )でクラスをインスタンス化して、従業員データをスキーマに追加できます。
Apache Avroを使用してスキーマに従ってデータを作成する手順を見てみましょう。
ステップ1
生成された emp クラスをインスタンス化します。
emp e1=new emp( );
ステップ2
セッターメソッドを使用して、最初の従業員のデータを挿入します。 たとえば、Omarという名前の従業員の詳細を作成しました。
e1.setName("omar");
e1.setAge(21);
e1.setSalary(30000);
e1.setAddress("Hyderabad");
e1.setId(001);
同様に、セッターメソッドを使用してすべての従業員の詳細を入力します。
ステップ3
*SpecificDatumWriter* クラスを使用して、 *DatumWriter* インターフェイスのオブジェクトを作成します。 これにより、Javaオブジェクトがメモリ内のシリアル化された形式に変換されます。 次の例では、 *emp* クラスの *SpecificDatumWriter* クラスオブジェクトをインスタンス化します。
DatumWriter<emp> empDatumWriter = new SpecificDatumWriter<emp>(emp.class);
ステップ4
*emp* クラスの *DataFileWriter* をインスタンス化します。 このクラスは、スキーマに準拠したデータのシーケンスシリアル化されたレコードを、スキーマ自体とともにファイルに書き込みます。 このクラスには、コンストラクターのパラメーターとして *DatumWriter* オブジェクトが必要です。
DataFileWriter<emp> empFileWriter = new DataFileWriter<emp>(empDatumWriter);
ステップ5
- create()*メソッドを使用して、指定されたスキーマに一致するデータを保存する新しいファイルを開きます。 このメソッドには、スキーマと、データが保存されるファイルのパスがパラメーターとして必要です。
次の例では、スキーマは* getSchema()メソッドを使用して渡され、データファイルはパスに保存されます-/home/Hadoop/Avro/serialized_file/emp.avro。*
empFileWriter.create(e1.getSchema(),new File("/home/Hadoop/Avro/serialized_file/emp.avro"));
ステップ6
以下に示すように* append()*メソッドを使用して、作成されたすべてのレコードをファイルに追加します-
empFileWriter.append(e1);
empFileWriter.append(e2);
empFileWriter.append(e3);
例–クラスを生成することによるシリアル化
次の完全なプログラムは、Apache Avroを使用してデータをファイルにシリアル化する方法を示しています-
import java.io.File;
import java.io.IOException;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumWriter;
public class Serialize {
public static void main(String args[]) throws IOException{
//Instantiating generated emp class
emp e1=new emp();
//Creating values according the schema
e1.setName("omar");
e1.setAge(21);
e1.setSalary(30000);
e1.setAddress("Hyderabad");
e1.setId(001);
emp e2=new emp();
e2.setName("ram");
e2.setAge(30);
e2.setSalary(40000);
e2.setAddress("Hyderabad");
e2.setId(002);
emp e3=new emp();
e3.setName("robbin");
e3.setAge(25);
e3.setSalary(35000);
e3.setAddress("Hyderabad");
e3.setId(003);
//Instantiate DatumWriter class
DatumWriter<emp> empDatumWriter = new SpecificDatumWriter<emp>(emp.class);
DataFileWriter<emp> empFileWriter = new DataFileWriter<emp>(empDatumWriter);
empFileWriter.create(e1.getSchema(), new File("/home/Hadoop/Avro_Work/with_code_gen/emp.avro"));
empFileWriter.append(e1);
empFileWriter.append(e2);
empFileWriter.append(e3);
empFileWriter.close();
System.out.println("data successfully serialized");
}
}
生成されたコードが配置されているディレクトリを参照します。 この場合、 home/Hadoop/Avro_work/with_code_gen にあります。
ターミナル内-
$ cd home/Hadoop/Avro_work/with_code_gen/
- GUIで-*
上記のプログラムをコピーして、 Serialize.java という名前のファイルに保存します
次のようにコンパイルして実行します-
$ javac Serialize.java
$ java Serialize
出力
data successfully serialized
プログラムで指定されたパスを確認すると、以下に示すように、生成されたシリアル化されたファイルを見つけることができます。
AVRO-生成クラスによる逆シリアル化
前に説明したように、スキーマに対応するクラスを生成するか、パーサーライブラリを使用して、Avroスキーマをプログラムに読み込むことができます。 この章では、クラスを生成してスキーマを読み取る方法と、Avroを使用してデータを*デシリアライズ*する方法について説明します。
クラスを生成することによる逆シリアル化
シリアル化されたデータは、ファイル emp.avro に保存されます。 Avroを使用して、デシリアライズして読み取ることができます。
以下の手順に従って、ファイルからシリアル化されたデータを逆シリアル化します。
ステップ1
*SpecificDatumReader* クラスを使用して、 *DatumReader* インターフェイスのオブジェクトを作成します。
DatumReader<emp>empDatumReader = new SpecificDatumReader<emp>(emp.class);
ステップ2
*emp* クラスの *DataFileReader* をインスタンス化します。 このクラスは、ファイルからシリアル化されたデータを読み取ります。 コンストラクターのパラメーターとして、 *Dataumeader* オブジェクトと、シリアル化されたデータが存在するファイルのパスが必要です。
DataFileReader<emp> dataFileReader = new DataFileReader(new File("/path/to/emp.avro"), empDatumReader);
ステップ3
*DataFileReader* のメソッドを使用して、逆シリアル化されたデータを印刷します。
- Readerに要素がある場合、* hasNext()*メソッドはブール値を返します。
- DataFileReader の* next()*メソッドは、リーダーにデータを返します。
while(dataFileReader.hasNext()){
em=dataFileReader.next(em);
System.out.println(em);
}
例–クラスを生成することによる逆シリアル化
次の完全なプログラムは、Avroを使用してファイル内のデータを逆シリアル化する方法を示しています。
import java.io.File;
import java.io.IOException;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.io.DatumReader;
import org.apache.avro.specific.SpecificDatumReader;
public class Deserialize {
public static void main(String args[]) throws IOException{
//DeSerializing the objects
DatumReader<emp> empDatumReader = new SpecificDatumReader<emp>(emp.class);
//Instantiating DataFileReader
DataFileReader<emp> dataFileReader = new DataFileReader<emp>(new
File("/home/Hadoop/Avro_Work/with_code_genfile/emp.avro"), empDatumReader);
emp em=null;
while(dataFileReader.hasNext()){
em=dataFileReader.next(em);
System.out.println(em);
}
}
}
生成されたコードが配置されているディレクトリを参照します。 この場合、* home/Hadoop/Avro_work/with_code_gen。*で
$ cd home/Hadoop/Avro_work/with_code_gen/
ここで、上記のプログラムをコピーして、 DeSerialize.java という名前のファイルに保存します。 次のようにコンパイルして実行します-
$ javac Deserialize.java
$ java Deserialize
出力
{"name": "omar", "id": 1, "salary": 30000, "age": 21, "address": "Hyderabad"}
{"name": "ram", "id": 2, "salary": 40000, "age": 30, "address": "Hyderabad"}
{"name": "robbin", "id": 3, "salary": 35000, "age": 25, "address": "Hyderabad"}
AVRO-パーサーを使用したシリアル化
スキーマに対応するクラスを生成するか、パーサーライブラリを使用して、Avroスキーマをプログラムに読み込むことができます。 Avroでは、データは常に対応するスキーマとともに保存されます。 したがって、コードを生成せずにスキーマをいつでも読み取ることができます。
この章では、パーサーライブラリを使用してスキーマを読み取る方法、およびAvroを使用してデータを*シリアル化する方法について説明します。
パーサーライブラリを使用したシリアル化
データをシリアル化するには、スキーマを読み取り、スキーマに従ってデータを作成し、Avro APIを使用してスキーマをシリアル化する必要があります。 次の手順は、コードを生成せずにデータをシリアル化します-
ステップ1
まず、ファイルからスキーマを読み取ります。 これを行うには、 Schema.Parser クラスを使用します。 このクラスは、さまざまな形式でスキーマを解析するメソッドを提供します。
スキーマが保存されているファイルパスを渡すことにより、 Schema.Parser クラスをインスタンス化します。
Schema schema = new Schema.Parser().parse(new File("/path/to/emp.avsc"));
ステップ2
以下に示すように、 GenericData.Record クラスをインスタンス化して、 GenericRecord インターフェイスのオブジェクトを作成します。 上記の作成されたスキーマオブジェクトをコンストラクタに渡します。
GenericRecord e1 = new GenericData.Record(schema);
ステップ3
*GenericData* クラスの* put()*メソッドを使用して、スキーマに値を挿入します。
e1.put("name", "ramu");
e1.put("id", 001);
e1.put("salary",30000);
e1.put("age", 25);
e1.put("address", "chennai");
ステップ4
*SpecificDatumWriter* クラスを使用して、 *DatumWriter* インターフェイスのオブジェクトを作成します。 Javaオブジェクトをメモリ内シリアル化形式に変換します。 次の例では、 *emp* クラスの *SpecificDatumWriter* クラスオブジェクトをインスタンス化します-
DatumWriter<emp> empDatumWriter = new SpecificDatumWriter<emp>(emp.class);
ステップ5
*emp* クラスの *DataFileWriter* をインスタンス化します。 このクラスは、スキーマに準拠したデータのシリアル化されたレコードを、スキーマ自体とともにファイルに書き込みます。 このクラスには、コンストラクターのパラメーターとして *DatumWriter* オブジェクトが必要です。
DataFileWriter<emp> dataFileWriter = new DataFileWriter<emp>(empDatumWriter);
ステップ6
- create()*メソッドを使用して、指定されたスキーマに一致するデータを保存する新しいファイルを開きます。 このメソッドには、スキーマと、データが保存されるファイルのパスがパラメーターとして必要です。
以下の例では、スキーマは* getSchema()*メソッドを使用して渡され、データファイルはパスに保存されます
/home/Hadoop/Avro/serialized_file/emp.avro。
empFileWriter.create(e1.getSchema(), new
File("/home/Hadoop/Avro/serialized_file/emp.avro"));
ステップ7
以下に示すように、* append()*メソッドを使用して、作成されたすべてのレコードをファイルに追加します。
empFileWriter.append(e1);
empFileWriter.append(e2);
empFileWriter.append(e3);
例–パーサーを使用したシリアル化
次の完全なプログラムは、パーサーを使用してデータをシリアル化する方法を示しています-
import java.io.File;
import java.io.IOException;
import org.apache.avro.Schema;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.DatumWriter;
public class Seriali {
public static void main(String args[]) throws IOException{
//Instantiating the Schema.Parser class.
Schema schema = new Schema.Parser().parse(new File("/home/Hadoop/Avro/schema/emp.avsc"));
//Instantiating the GenericRecord class.
GenericRecord e1 = new GenericData.Record(schema);
//Insert data according to schema
e1.put("name", "ramu");
e1.put("id", 001);
e1.put("salary",30000);
e1.put("age", 25);
e1.put("address", "chenni");
GenericRecord e2 = new GenericData.Record(schema);
e2.put("name", "rahman");
e2.put("id", 002);
e2.put("salary", 35000);
e2.put("age", 30);
e2.put("address", "Delhi");
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema);
DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter);
dataFileWriter.create(schema, new File("/home/Hadoop/Avro_work/without_code_gen/mydata.txt"));
dataFileWriter.append(e1);
dataFileWriter.append(e2);
dataFileWriter.close();
System.out.println(“data successfully serialized”);
}
}
生成されたコードが配置されているディレクトリを参照します。 この場合、 home/Hadoop/Avro_work/without_code_gen にあります。
$ cd home/Hadoop/Avro_work/without_code_gen/
次に、上記のプログラムをコピーして、 Serialize.java という名前のファイルに保存します。 次のようにコンパイルして実行します-
$ javac Serialize.java
$ java Serialize
出力
data successfully serialized
プログラムで指定されたパスを確認すると、以下に示すように、生成されたシリアル化されたファイルを見つけることができます。
AVRO-パーサーを使用した逆シリアル化
前述のように、スキーマに対応するクラスを生成するか、パーサーライブラリを使用して、Avroスキーマをプログラムに読み込むことができます。 Avroでは、データは常に対応するスキーマとともに保存されます。 したがって、シリアル化されたアイテムをコード生成なしでいつでも読み取ることができます。
この章では、パーサーライブラリを使用してスキーマを読み取る方法、およびAvroを使用してデータを*デシリアライズする方法について説明します。
パーサーライブラリを使用した逆シリアル化
シリアル化されたデータは、 mydata.txt ファイルに保存されます。 Avroを使用して、デシリアライズして読み取ることができます。
以下の手順に従って、ファイルからシリアル化されたデータを逆シリアル化します。
ステップ1
まず、ファイルからスキーマを読み取ります。 これを行うには、 Schema.Parser クラスを使用します。 このクラスは、さまざまな形式でスキーマを解析するメソッドを提供します。
スキーマが保存されているファイルパスを渡すことにより、 Schema.Parser クラスをインスタンス化します。
Schema schema = new Schema.Parser().parse(new File("/path/to/emp.avsc"));
ステップ2
*SpecificDatumReader* クラスを使用して、 *DatumReader* インターフェイスのオブジェクトを作成します。
DatumReader<emp>empDatumReader = new SpecificDatumReader<emp>(emp.class);
ステップ3
*DataFileReader* クラスをインスタンス化します。 このクラスは、ファイルからシリアル化されたデータを読み取ります。 コンストラクターのパラメーターとして、 *DatumReader* オブジェクトと、シリアル化されたデータが存在するファイルのパスが必要です。
DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(new File("/path/to/mydata.txt"), datumReader);
ステップ4
*DataFileReader* のメソッドを使用して、逆シリアル化されたデータを印刷します。
- Readerに要素がある場合、* hasNext()*メソッドはブール値を返します .
- DataFileReader の* next()*メソッドは、リーダーにデータを返します。
while(dataFileReader.hasNext()){
em=dataFileReader.next(em);
System.out.println(em);
}
例–パーサーライブラリを使用した逆シリアル化
次の完全なプログラムは、パーサーライブラリを使用してシリアル化されたデータを逆シリアル化する方法を示しています-
public class Deserialize {
public static void main(String args[]) throws Exception{
//Instantiating the Schema.Parser class.
Schema schema = new Schema.Parser().parse(new File("/home/Hadoop/Avro/schema/emp.avsc"));
DatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord>(schema);
DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(new File("/home/Hadoop/Avro_Work/without_code_gen/mydata.txt"), datumReader);
GenericRecord emp = null;
while (dataFileReader.hasNext()) {
emp = dataFileReader.next(emp);
System.out.println(emp);
}
System.out.println("hello");
}
}
生成されたコードが配置されているディレクトリを参照します。 この場合、それは home/Hadoop/Avro_work/without_code_gen にあります。
$ cd home/Hadoop/Avro_work/without_code_gen/
上記のプログラムをコピーして、 DeSerialize.java という名前のファイルに保存します。 次のようにコンパイルして実行します-
$ javac Deserialize.java
$ java Deserialize
出力
{"name": "ramu", "id": 1, "salary": 30000, "age": 25, "address": "chennai"}
{"name": "rahman", "id": 2, "salary": 35000, "age": 30, "address": "Delhi"}