AVRO - 序列化


数据序列化有两个目的 -

  • 用于持久存储

  • 通过网络传输数据

什么是序列化?

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

Java 中的序列化

Java 提供了一种称为对象序列化的机制,其中对象可以表示为字节序列,其中包括对象的数据以及有关对象类型和对象中存储的数据类型的信息。

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

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

Hadoop 中的序列化

通常在像Hadoop这样的分布式系统中,序列化的概念用于进程间通信持久存储

进程间通信

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

  • RPC 使用内部序列化将消息转换为二进制格式,然后通过网络发送到远程节点。在另一端,远程系统将二进制流反序列化为原始消息。

  • RPC 序列化格式要求如下 -

    • 紧凑- 充分利用网络带宽,这是数据中心中最稀缺的资源。

    • 快速- 由于节点之间的通信在分布式系统中至关重要,因此序列化和反序列化过程应该很快,从而产生更少的开销。

    • 可扩展- 协议随着时间的推移而变化以满足新的要求,因此以受控方式为客户端和服务器发展协议应该很简单。

    • 可互操作- 消息格式应支持用不同语言编写的节点。

持久存储

持久存储是一种数字存储设施,不会因断电而丢失数据。文件、文件夹、数据库是持久存储的示例。

可写接口

这是 Hadoop 中的接口,提供序列化和反序列化的方法。下表描述了这些方法 -

编号 方法和说明
1

无效readFields(数据输入)

该方法用于反序列化给定对象的字段。

2

无效写入(数据输出)

该方法用于序列化给定对象的字段。

可写的类似接口

它是WritableComparable接口的组合。该接口继承了Hadoop的Writable接口以及Java的Comparable接口。因此它提供了数据序列化、反序列化和比较的方法。

编号 方法和说明
1

int 比较(对象类)

该方法将当前对象与给定对象 obj 进行比较。

除了这些类之外,Hadoop 还支持许多实现 WritableComparable 接口的包装类。每个类都包装一个 Java 原始类型。Hadoop 序列化的类层次结构如下 -

Hadoop 序列化层次结构

这些类对于在 Hadoop 中序列化各种类型的数据非常有用。例如,让我们考虑IntWritable类。让我们看看这个类如何用于在 Hadoop 中序列化和反序列化数据。

可写类

此类实现Writable、ComparableWritableComparable接口。它在其中包装了整数数据类型。此类提供用于序列化和反序列化整数类型数据的方法。

构造函数

编号 概括
1 可写()
2 IntWritable(整数值)

方法

编号 概括
1

int 获取()

使用此方法,您可以获得当前对象中存在的整数值。

2

无效readFields(数据输入)

此方法用于反序列化给定DataInput对象中的数据。

3

无效集(整数值)

该方法用于设置当前IntWritable对象的值。

4

无效写入(数据输出)

该方法用于将当前对象中的数据序列化到给定的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());
   }
}

Hadoop 相对于 Java 序列化的优势

Hadoop 的基于 Writable 的序列化能够通过重用 Writable 对象来减少对象创建开销,而这对于 Java 的本机序列化框架来说是不可能的。

Hadoop 序列化的缺点

要序列化 ​​Hadoop 数据,有两种方法 -

  • 您可以使用Hadoop 原生库提供的Writable类。

  • 您还可以使用以二进制格式存储数据的序列文件。

这两种机制的主要缺点是WritablesSequenceFiles只有 Java API,不能用任何其他语言编写或读取它们。

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