Avro 简明教程

AVRO - Serialization

数据序列化有以下两个目的 −

  1. For persistent storage

  2. 通过网络传输数据

What is Serialization?

序列化是指将数据结构或对象状态转换为二进制或文本形式,以便通过网络传输数据或存储在某些持久存储中。一旦通过网络传输数据或从持久存储中检索数据,就需要再次反序列化数据。序列化称为 marshalling ,而反序列化称为 unmarshalling

Serialization in Java

Java 提供了一种称为 object serialization 的机制,对象可以用作一个字节序列,其中包括对象的数据以及对象类型和存储在对象中的数据类型的信息。

将序列化的对象写入文件后,可以从该文件中读取并反序列化它。也就是说,表示对象及其数据的类型信息和字节可用于在内存中重新创建对象。

ObjectInputStreamObjectOutputStream 类分别用于在 Java 中序列化和反序列化对象。

Serialization in Hadoop

通常,在 Hadoop 等分布式系统中,序列化概念用于 Interprocess CommunicationPersistent Storage

Interprocess Communication

  1. 为了在连接到网络中的节点之间建立进程间通信,采用了 RPC 技术。

  2. RPC 使用内部序列化在将消息发送到远程节点之前将其转换为二进制格式。在另一端,远程系统将二进制流反序列化为原始消息。

  3. 对 RPC 序列化格式的要求如下 − Compact − 充分利用网络带宽,这是数据中心中最宝贵的资源。 Fast − 由于节点之间的通信在分布式系统中至关重要,因此序列化和反序列化过程应快速,产生的开销较小。 Extensible − 协议会随着时间推移而改变,以满足新要求,因此应以受控方式轻松地为客户端和服务器发展协议。 Interoperable − 消息格式应支持用不同编程语言编写的节点。

Persistent Storage

持久性存储是一种数字存储设施,当电源供应中断时,它不会丢失其数据。文件、文件夹和数据库是持久性存储的示例。

Writable Interface

这是 Hadoop 中的接口,它提供用于序列化和反序列化的多种方法。下表对这些方法进行了描述 −

S.No.

Methods and Description

1

void readFields(DataInput in) 该方法用于反序列化给定对象字段。

2

void write(DataOutput out) 该方法用于序列化给定对象字段。

Writable Comparable Interface

它结合了 WritableComparable 接口。该接口继承了 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 Class

此类实现了 Writable, Comparable,WritableComparable 接口。它包装了一个整数数据类型。此类提供了用于序列化和反序列化整数类型数据的的方法。

Constructors

S.No.

Summary

1

IntWritable()

2

IntWritable( int value)

Methods

S.No.

Summary

1

int get() 使用此方法可以获得当前对象中存在的整数值。

2

void readFields(DataInput in) 此方法用于反序列化给定 DataInput 对象中的数据。

3

void set(int value) 此方法用于设置当前 IntWritable 对象的值。

4

void write(DataOutput out) 此方法用于序列化当前对象中的数据到给定的 DataOutput 对象。

Serializing the Data in Hadoop

下面讨论序列化整数类型数据的过程。

  1. 通过包装一个整数值来实例化 IntWritable 类。

  2. Instantiate ByteArrayOutputStream class.

  3. 实例化 DataOutputStream 类,并将 ByteArrayOutputStream 类的对象传递给它。

  4. 使用 write() 方法在 IntWritable 对象中序列化整数值。此方法需要 DataOutputStream 类的对象。

  5. 已序列化的数据将存储在字节数组对象中,该对象在实例化时作为参数传递给 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

下面讨论反序列化整数类型数据的过程:

  1. 通过包装一个整数值来实例化 IntWritable 类。

  2. Instantiate ByteArrayOutputStream class.

  3. 实例化 DataOutputStream 类,并将 ByteArrayOutputStream 类的对象传递给它。

  4. 使用 IntWritable 类的 readFields() 方法反序列化 DataInputStream 对象中的数据。

  5. 反序列化的数据将存储在 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 数据,有两种办法:

  1. 可以使用 Hadoop 的原生库提供的 Writable 类。

  2. 您还可以使用存储二进制格式数据的 Sequence Files

这两种机制的主要缺点是 WritablesSequenceFiles 仅有一个 Java API,不能用其他任何语言编写或读入。

因此,任何使用上述两种机制在 Hadoop 中创建的文件都无法被任何其他第三方语言读取,这使得 Hadoop 成为一个限制盒子。为了解决这一缺点,Doug Cutting 创建了 Avro, ,它是一个 language independent data structure