Avro 简明教程
AVRO - Serialization
数据序列化有以下两个目的 −
-
For persistent storage
-
通过网络传输数据
What is Serialization?
序列化是指将数据结构或对象状态转换为二进制或文本形式,以便通过网络传输数据或存储在某些持久存储中。一旦通过网络传输数据或从持久存储中检索数据,就需要再次反序列化数据。序列化称为 marshalling ,而反序列化称为 unmarshalling 。
Serialization in Java
Java 提供了一种称为 object serialization 的机制,对象可以用作一个字节序列,其中包括对象的数据以及对象类型和存储在对象中的数据类型的信息。
将序列化的对象写入文件后,可以从该文件中读取并反序列化它。也就是说,表示对象及其数据的类型信息和字节可用于在内存中重新创建对象。
ObjectInputStream 和 ObjectOutputStream 类分别用于在 Java 中序列化和反序列化对象。
Serialization in Hadoop
通常,在 Hadoop 等分布式系统中,序列化概念用于 Interprocess Communication 和 Persistent Storage 。
Interprocess Communication
-
为了在连接到网络中的节点之间建立进程间通信,采用了 RPC 技术。
-
RPC 使用内部序列化在将消息发送到远程节点之前将其转换为二进制格式。在另一端,远程系统将二进制流反序列化为原始消息。
-
对 RPC 序列化格式的要求如下 − Compact − 充分利用网络带宽,这是数据中心中最宝贵的资源。 Fast − 由于节点之间的通信在分布式系统中至关重要,因此序列化和反序列化过程应快速,产生的开销较小。 Extensible − 协议会随着时间推移而改变,以满足新要求,因此应以受控方式轻松地为客户端和服务器发展协议。 Interoperable − 消息格式应支持用不同编程语言编写的节点。
Writable Interface
这是 Hadoop 中的接口,它提供用于序列化和反序列化的多种方法。下表对这些方法进行了描述 −
S.No. |
Methods and Description |
1 |
void readFields(DataInput in) 该方法用于反序列化给定对象字段。 |
2 |
void write(DataOutput out) 该方法用于序列化给定对象字段。 |
Writable Comparable Interface
它结合了 Writable 和 Comparable 接口。该接口继承了 Hadoop 的 Writable 接口和 Java 的 Comparable 接口。所以它提供了用于数据序列化、反序列化和比较的方法。
S.No. |
Methods and Description |
1 |
int compareTo(class obj) 该方法将当前对象与给定对象 obj 进行比较。 |
除了这些类以外,Hadoop 还支持许多实现 WritableComparable 接口的包装类。每个类都包装一个 Java 原始类型。Hadoop 序列化的类层次结构如下 −
这些类有助于序列化 Hadoop 中各种类型的数据。例如,我们考虑 IntWritable 类。我们看看是如何使用此类来序列化和反序列化 Hadoop 中的数据的。
IntWritable Class
此类实现了 Writable, Comparable, 和 WritableComparable 接口。它包装了一个整数数据类型。此类提供了用于序列化和反序列化整数类型数据的的方法。
Serializing the Data in Hadoop
下面讨论序列化整数类型数据的过程。
-
通过包装一个整数值来实例化 IntWritable 类。
-
Instantiate ByteArrayOutputStream class.
-
实例化 DataOutputStream 类,并将 ByteArrayOutputStream 类的对象传递给它。
-
使用 write() 方法在 IntWritable 对象中序列化整数值。此方法需要 DataOutputStream 类的对象。
-
已序列化的数据将存储在字节数组对象中,该对象在实例化时作为参数传递给 DataOutputStream 类。将对象中的数据转换为字节数组。
Example
以下示例显示了如何在 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();
}
}
Deserializing the Data in Hadoop
下面讨论反序列化整数类型数据的过程:
-
通过包装一个整数值来实例化 IntWritable 类。
-
Instantiate ByteArrayOutputStream class.
-
实例化 DataOutputStream 类,并将 ByteArrayOutputStream 类的对象传递给它。
-
使用 IntWritable 类的 readFields() 方法反序列化 DataInputStream 对象中的数据。
-
反序列化的数据将存储在 IntWritable 类的对象中。可以使用此类的 get() 方法检索此数据。
Example
以下示例显示了如何在 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());
}
}
Advantage of Hadoop over Java Serialization
Hadoop 的基于可写对象的序列化能够通过重新使用可写对象来减少对象创建开销,而 Java 的原生序列化框架不能这么做。
Disadvantages of Hadoop Serialization
要序列化 Hadoop 数据,有两种办法:
-
可以使用 Hadoop 的原生库提供的 Writable 类。
-
您还可以使用存储二进制格式数据的 Sequence Files 。
这两种机制的主要缺点是 Writables 和 SequenceFiles 仅有一个 Java API,不能用其他任何语言编写或读入。
因此,任何使用上述两种机制在 Hadoop 中创建的文件都无法被任何其他第三方语言读取,这使得 Hadoop 成为一个限制盒子。为了解决这一缺点,Doug Cutting 创建了 Avro, ,它是一个 language independent data structure 。