首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 序列化與 Hadoop Writable 序列化深度對比:原理、實現與選型指南

     編輯:Java 相關知識

第一部分:Java 原生序列化

核心概念

序列化:將對象狀態轉為字節流(持久化/網絡傳輸)
反序列化:字節流還原為對象

實現步驟

  1. 類實現 Serializable 標記接口
  2. 定義 serialVersionUID(強烈建議顯式聲明)
  3. 使用 ObjectOutputStream.writeObject() / ObjectInputStream.readObject()

代碼示例

// 實體類
public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private String id, name;
    // getter/setter/構造器
}

// 序列化
try (FileOutputStream fos = new FileOutputStream("d:/student");
     ObjectOutputStream oos = new ObjectOutputStream(fos)) {
    oos.writeObject(new Student("201441413110", "yang"));
}

// 反序列化
try (FileInputStream fis = new FileInputStream("d:/student");
     ObjectInputStream ois = new ObjectInputStream(fis)) {
    Student stu = (Student) ois.readObject();
    System.out.println(stu.getId() + " " + stu.getName());
}

字節流結構分析

  • 魔數 AC ED + 版本 00 05
  • 類描述:類名長度、類名、serialVersionUID
  • 字段元數據:非 transient/static 字段名、類型、值
  • 引用對象遞歸序列化(處理循環引用)

第二部分:Hadoop Writable 序列化

設計動機

針對分布式場景優化:

  • 緊湊:無類元數據,僅存值
  • 高速:直接操作 DataInput/DataOutput,避免反射
  • 可排序:支持 WritableComparable,MapReduce Shuffle 階段零拷貝比較
  • 可重用:反序列化復用對象,減少 GC

核心接口體系

// 基礎接口
public interface Writable {
    void write(DataOutput out) throws IOException;
    void readFields(DataInput in) throws IOException;
}

// 可比較接口(MapReduce Key 必須)
public interface WritableComparable<T> extends Writable, Comparable<T> {}

// 高效比較器(無需反序列化即可比較字節流)
public interface RawComparator<T> extends Comparator<T> {
    int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
}

// 通用實現工廠
RawComparator<IntWritable> cmp = WritableComparator.get(IntWritable.class);

IntWritable 完整示例

public class Serialize {
    public static byte[] serialize(Writable w) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(out);
        w.write(dos);
        dos.close();
        return out.toByteArray();
    }

    public static void deserialize(Writable w, byte[] bytes) throws IOException {
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        DataInputStream dis = new DataInputStream(in);
        w.readFields(dis);
        dis.close();
    }

    public static void main(String[] args) throws IOException {
        IntWritable src = new IntWritable(20);
        IntWritable dest = new IntWritable();
        deserialize(dest, serialize(src));
        System.out.println(dest.get()); // 20
    }
}

第三部分:Hadoop 序列化框架擴展

org.apache.hadoop.io.serializer 包提供插件化機制:

  • Serialization<T>:判斷類型支持、產出 Serializer/Deserializer
  • WritableSerialization:Writable 類型的默認實現
  • 支持 Java 基本類型(String、Integer 等)但效率低於 Writable

為什麼 Hadoop 放棄 Java 原生序列化?

維度Java SerializationHadoop Writable
字節體積大(含類名、UID、引用結構)小(僅有效負載)
隨機訪問不支持(流式讀取)支持(定長/可分片)
排序性能需全反序列化後比較RawComparator 直接比較字節
對象重用每次 new ObjectreadFields 復用對象
跨語言困難困難(同屬 JVM 生態)

選型建議

  • 單體應用、RPC、緩存 → Java 序列化 / Protobuf / Kryo
  • MapReduce、Spark、HBase → 強制 Writable
  • 異構系統集成 → Avro / Protobuf / Thrift(支持 Schema 演進)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved