자바 Object Serialization 과 Hadoop 직렬 화

1,Java Object 직렬 화
1.직렬 화(Serialization)가 무엇 입 니까?
직렬 화 는 네트워크 에서 전송 하거나 디스크 에 영구적 으로 저장 할 수 있 도록 구조 화 대상 을 바이트 흐름 으로 바 꾸 는 과정 을 말한다.역 직렬 화 는 바이트 흐름 을 구조 화 대상 으로 되 돌 리 는 역 과정 을 말한다.간단 한 이 해 는 대상 이 바이트 흐름 으로 바 뀌 어 전송 과 저장 을 하고 바이트 흐름 을 대상 으로 바 꾸 어 대상 을 원래 의 상태 로 회복 하 는 것 이다.
2,직렬 화(Serialization)의 역할
(1)메모리 의 대상 상 태 를 파일 이나 데이터베이스 에 저장 하 는 지구 화 메커니즘
(2)일종 의 통신 메커니즘 으로 소켓 으로 네트워크 에서 대상 을 전송 한다.
(3)자바 원 격 방법 호출(RMI)대상 호출 필요 시,
3.Serializable 인터페이스의 대상 의 직렬 화 를 실현 했다.
자바.io 패키지 에서 인터페이스 Serialization 은 대상 직렬 화 를 실현 하 는 도구 로 사용 되 며,Serialization 과 같은 대상 만 직렬 화 될 수 있 습 니 다.Serializable 인터페이스 에는 어떤 방법 도 없습니다.Serializable 인 터 페 이 스 를 실현 하 겠 다 는 성명 이 있 을 때,이러한 종류의 직렬 화 프로 토 콜 에 참가 하 는 것 을 나 타 낼 뿐,어떠한 특수 한 방법 도 실현 할 필요 가 없습니다.
대상 을 정렬 하려 면 먼저 OutputStream 대상 을 만 든 다음 Object OutputStream 대상 에 밀봉 해 야 합 니 다.이때 writeObject()방법 을 호출 하여 대상 을 직렬 화하 여 OutputStream 에 보 냅 니 다.역 직렬 화 할 때 하나의 InputStream 을 Object InputStream 에 밀봉 한 다음 readObject()를 호출 해 야 합 니 다.결 과 는 Object 대상 이 고 마지막 으로 필요 한 대상 으로 전환 해 야 합 니 다.주의해 야 할 것 은 Serializable 대상 을 역 직렬 화 하 는 과정 에서 부족 한 구조 기 를 포함 하여 모든 대상 이 InputStream 에서 데 이 터 를 얻어 회복 되 었 다 는 것 이다.대상 의 직렬 화 는 바이트 에 대한 것 이기 때문에 InputStream 과 OutputStream 차원 구 조 를 사용한다.
학생 서열 화

package cn.test.serializable;
/**
 *        Serializable  
 * @author Young
 * created on 2017-5-25
 */
import java.io.Serializable;
public class Student implements Serializable {
  private String id;
  private String name;
  public Student (String id,String name){
    this.id=id;
    this.name=name;
  }
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}
서열 화

package cn.test.serializable;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
 *    
 * @author Young
 * created on 2017-5-25
 */
public class TestSerializable {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Student stu=new Student("201441413110","yang");
    try {
      FileOutputStream out=new FileOutputStream("d:\\student");//  OutputStream  
      ObjectOutputStream ob=new ObjectOutputStream(out);//     ObjectOutputStream   
      ob.writeObject(stu);//  writeObject()            OutputStream,   d:\\student 
      ob.close();
      out.close();
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
역 직렬 화

package cn.test.serializable;
/**
 *     
 * @author Young
 * created on 2017-5-25
 */
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class TestDeserializable {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    FileInputStream in;
    Student stu;
    try {
      in = new FileInputStream("d:\\student");
      ObjectInputStream ob=new ObjectInputStream(in);//InputStream   ObjectInputStream 
      stu=(Student) ob.readObject();//  readObject(),        Object  ,               .
      ob.close();
      in.close();
      System.out.println(stu.getId());
      System.out.println(stu.getName());
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
직렬 화 메커니즘 이 스 트림 에 기 록 된 데 이 터 는?
1.성명 과 태그,예 를 들 어 성명 은 직렬 화 프로 토 콜,직렬 화 프로 토 콜 버 전,성명 은 새로운 대상 이 고 성명 은 여기 서 새로운 Class 를 시작 하고 끝 표 시 를 시작 합 니 다.
2.대상 이 속 한 클래스,클래스 의 길이,
3.SerialVersionUID,직렬 화 ID,지정 되 지 않 으 면 알고리즘 에 의 해 8byte 의 ID 를 무 작위 로 생 성 합 니 다.
4.모든 비 transient 와 비 static 속성의 개수 와 이름.이름 길이,속성의 값.
이것 은 단순 대상 이 직렬 화 된 후에 스 트림 에 기 록 된 데이터 일 뿐이다.복잡 한 대상 의 서열 화 라면 더 많은 정 보 를 포함 할 것 이다.예 를 들 어 다른 대상 을 구성원 변수 로 인용 하 는 것 은 인용 대상 도 직렬 화 하 는 것 이다.그리고 직렬 화 할 때 대상 의 상태 만 저장 하고 대상 을 상관 하지 않 는 방법 도 있다.부모 클래스 가 직렬 화 를 실현 하면 하위 클래스 는 자동 으로 직렬 화 를 실현 하고 직렬 화 인 터 페 이 스 를 명시 적 으로 실현 할 필요 가 없다.한 대상 의 인 스 턴 스 변 수 는 다른 대상 을 참조 하고 이 대상 을 직렬 화 할 때 도 인용 대상 을 직렬 화 합 니 다.
2.Hadoop 직렬 화
hadop 은 노드 간 의 내부 통신 에서 RPC 를 사용 합 니 다.RPC 프로 토 콜 은 메 시 지 를 바 이 너 리 바이트 로 번역 하여 원 격 노드 에 보 내 고 원 격 노드 는 반 직렬 화 를 통 해 바 이 너 리 를 원 격 정보 로 전환 합 니 다.
Hadoop 은 자신의 직렬 화 된 형식 인 Writable 을 사용 합 니 다.절대적 으로 치밀 하고 빠 르 지만 자바 이외 의 언어 로 확장 하고 사용 하기 가 쉽 지 않 습 니 다.
1,쓰기 인터페이스
Writable 인 터 페 이 스 는 두 가지 방법 을 정의 합 니 다.하 나 는 그 상 태 를 DataOutput 바 이 너 리 흐름 에 기록 하고 다른 하 나 는 DataInput 바 이 너 리 흐름 에서 그 상 태 를 읽 습 니 다.
구현 코드

package Hadoop.writable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Writable;
/**
 * hadoop         
 * @author Young
 * created by 2017-6-9
 */
public class Serialize {
  public static byte[] serialize(Writable writable) throws IOException{
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataout = new DataOutputStream(out);
    try {
      writable.write(dataout);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      dataout.close();
    }
    return out.toByteArray();
  }
  public static byte[] deserialize(Writable writable ,byte[] bytes) throws IOException{
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    DataInputStream datain = new DataInputStream(in);
    try {
      writable.readFields(datain);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    finally{
      datain.close();
    }
    return bytes;
  }
  public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    IntWritable intwritable = new IntWritable(20);
    IntWritable newwriatble =new IntWritable();
    byte[] bytes=Serialize.serialize(intwritable);
    deserialize(newwriatble,bytes);
    System.out.println(newwriatble.get());
  }
}
2.Hadoop 직렬 화 체제 에는 또 다른 몇 가지 중요 한 인터페이스 가 포함 되 어 있다.Writable Comparable,RawComparator 와 Writable Comparator
Writable Comparable 은 유형 비교 능력 을 제공 하고 Writable 인터페이스 와 Comparable 인 터 페 이 스 를 계승 하 며 그 중에서 Comparable 은 유형 비 교 를 한다.ByteWritable,IntWritable,DoubleWritable 등 자바 기본 유형 에 대응 하 는 Writable 유형 은 모두 Writable Comparable 에서 계승 합 니 다.
Writable Comparable 인터페이스

package org.apache.hadoop.io;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Stable;
import org.apache.hadoop.io.Writable;
@Public
@Stable
public interface WritableComparable<T> extends Writable, Comparable<T> {
}
MapReduce 에 있어 유형 은 매우 중요 합 니 다.중간 에 키 기반 정렬 단계 가 있 기 때 문 입 니 다.Hadoop 은 효율 적 인 비교 능력 을 가 진 RawComparator 인 터 페 이 스 를 제공 했다.
RawComparator 인터페이스

package org.apache.hadoop.io;
import java.util.Comparator;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Stable;
@Public
@Stable
public interface RawComparator<T> extends Comparator<T> {
  int compare(byte[] arg0, int arg1, int arg2, byte[] arg3, int arg4, int arg5);
}
이 인 터 페 이 스 는 데이터 흐름 의 기록 을 직접 비교 할 수 있 도록 해 주 며,먼저 데이터 흐름 을 대상 으로 정렬 하지 않 아 도 되 며,이렇게 하면 새로운 대상 이외 의 비용 을 피 할 수 있다.
Writable Comparator 는 Writable Comparable 류 를 계승 하 는 RawComparator 류 에 대한 일반적인 구현 입 니 다.두 가지 주요 기능 을 제공 하 다.1.원시 적 인 copare()방법 에 대한 기본 적 인 실현 을 제공 합 니 다.이 방법 은 흐름 에서 비교 할 대상 을 역 직렬 화하 고 대상 의 copare()방법 을 호출 할 수 있 습 니 다.2.RawComparator 인 스 턴 스 의 공장 역할 을 합 니 다.예 를 들 어 IntWritable 의 comparator 를 얻 기 위해 직접 호출 할 수 있 습 니 다.

RawComparator<IntWritable>comparator=WritableComparator.get(IntWritable.class);
다음은'하 둡 권위 가이드'의 예 다.

package cn.serialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.RawComparator;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparator;
public class TestWritable {
  //   
  public static byte[] serialize(Writable writable) throws IOException{
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataOut= new DataOutputStream(out);
    writable.write(dataOut);
    dataOut.close();
    return out.toByteArray();
  }
  //    
  public static byte[] deserialize(Writable writable, byte[] bytes) throws IOException{
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    DataInputStream dataIn = new DataInputStream(in);
    writable.readFields(dataIn);
    dataIn.close();
    return bytes;
  }
  public static void main(String[] args) throws IOException {
    @SuppressWarnings("unchecked")
    RawComparator <IntWritable> comparator = WritableComparator.get(IntWritable.class);
    IntWritable w1 = new IntWritable(163);
    IntWritable w2 = new IntWritable(67);
    byte[] b1 = serialize(w1);
    byte[] b2 = serialize(w2);
    System.out.println(b1);
    System.out.println(b2);
    System.out.println(comparator.compare(w1, w2));//WritableComparator  compare(),w1>w2 -> 1;w1<w2 -> -1 ; w1=w2 -> 0
  System.out.println(comparator.compare(b1,0,b1.length,b2,0,b2.length));
  }
}
3.Hadoop 직렬 화 프레임 워 크
대부분의 MapReduce 프로그램 은 Writable 형식의 key,value 를 사용 하지만 모든 MapReduce API 가 강제로 사용 하 는 것 은 아 닙 니 다.사실 모든 유형 을 사용 할 수 있 습 니 다.하나의 메커니즘 만 있 으 면 모든 유형 을 유형 과 바 이 너 리 로 전환 할 수 있 습 니 다.이 를 위해 Hadoop 은 org.apache.hadop.io.serializer 패키지 에서 WritableSerialization 류 는 Writable 유형의 Serialization 을 지원 합 니 다.
WritableSerialization 클래스

public class WritableSerialization extends Configured implements Serialization<Writable> {...}
직렬 화 인터페이스
open()인터페이스,직렬 화 인터페이스,close 인터페이스 정의

public interface Serializer<T> {
  void open(OutputStream arg0) throws IOException;
  void serialize(T arg0) throws IOException;
  void close() throws IOException;
}
Deserializer 인터페이스
open()인터페이스,역 직렬 화 인터페이스,close 인터페이스 정의

public interface Deserializer<T> {
  void open(InputStream arg0) throws IOException;
  T deserialize(T arg0) throws IOException;
  void close() throws IOException;
}
직렬 화 인터페이스
인 터 페 이 스 를 정의 하여 입력 을 지원 하 는 클래스 를 판단 하고 입력 클래스 에 따라 직렬 화 인터페이스 와 반 직렬 화 인 터 페 이 스 를 제공 합 니 다.

public interface Serialization<T> {
  boolean accept(Class<?> arg0);
  Serializer<T> getSerializer(Class<T> arg0);
  Deserializer<T> getDeserializer(Class<T> arg0);
}
API 문 서 를 볼 수 있 는 인터페이스 가 몇 개 더 있 습 니 다.
비록 이것 은 우리 가 MapReduce 에서 자바 형식 을 사용 하 는 데 편리 하지만,예 를 들 어 String,Integer 등 이다.하지만 이 는 Writable 보다 효율 적 이지 못 하 다.
Hadoop 에서 자바 Object Serialization 을 사용 하지 않 는 이유
1.자바 Object Serialization 은 간소화 되 지 않 습 니 다.예 를 들 어 본 고 에서 언급 한 자바 Object Serialization 직렬 화 된 바이트 흐름 은 많은 정 보 를 포함 합 니 다.예 를 들 어 유형 명 과 대상 등 입 니 다.
2.대상 은 직렬 화 에서 인용 만 저장 하고 인용 이 나타 날 수 있 는 위 치 는 무 작위 입 니 다.직렬 화 된 대상 앞에서 도 그 뒤에 도 있 을 수 있 습 니 다.그러면 무 작위 방문 과 정렬 에 영향 을 줄 수 있 습 니 다.오류 가 발생 하면 전체 뒤의 직렬 화 는 모두 오류 가 발생 합 니 다.Writable 은 무 작위 방문 과 정렬 을 지원 합 니 다.흐 르 는 기록 은 서로 독립 되 어 있 기 때문이다.
3.자바 직렬 화 는 매번 반 직렬 화 될 때마다 대상 을 다시 만 들 고 메모리 소모 가 많 으 며 Writable 은 다시 사용 할 수 있 습 니 다.
위 에서 말씀 드 린 것 은 편집장 님 께 서 소개 해 주신 자바 Object Serialization 과 Hadoop 의 서열 화 입 니 다.여러분 께 도움 이 되 셨 으 면 좋 겠 습 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.편집장 님 께 서 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기