📜  AVRO-序列化

📅  最后修改于: 2020-12-02 05:24:27             🧑  作者: Mango


数据被序列化为两个目标-

  • 用于持久存储

  • 通过网络传输数据

什么是序列化?

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

Java序列化

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

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

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

Hadoop中的序列化

通常,在诸如Hadoop之类的分布式系统中,序列化的概念用于进程间通信持久性存储

进程间通讯

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

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

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

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

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

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

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

永久储存

永久存储是一种数字存储设备,不会因电源中断而丢失其数据。文件,文件夹,数据库是持久性存储的示例。

可写界面

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

S.No. Methods and Description
1

void readFields(DataInput in)

This method is used to deserialize the fields of the given object.

2

void write(DataOutput out)

This method is used to serialize the fields of the given object.

可写可比接口

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

S.No. Methods and Description
1

int compareTo(class obj)

This method compares current object with the given object obj.

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

Hadoop序列化层次结构

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

可写类

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

建设者

S.No. Summary
1 IntWritable()
2 IntWritable( int value)

方法

S.No. Summary
1

int get()

Using this method you can get the integer value present in the current object.

2

void readFields(DataInput in)

This method is used to deserialize the data in the given DataInput object.

3

void set(int value)

This method is used to set the value of the current IntWritable object.

4

void write(DataOutput out)

This method is used to serialize the data in the current object to the given DataOutput object.

在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类。

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

这两种机制的主要缺点是可写文件SequenceFiles仅具有Java API,并且不能用任何其他语言编写或读取它们。

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