1. 序列化從頭說 在面向對象程序設計中,類是個很重要的概念。所謂“類”,可以將它想像成建筑圖紙,而對象就是根據圖紙蓋的大樓。類,規定了對象的一切。根據建筑圖紙造房子,蓋出來的就是大樓,等同于將類進行實例化,得到的就是對象。 一開始,在源代碼里,類的定義是明確的,但對象的行為有些地方是明確的,有些地方是不明確的。對象里不明確地方,是因為對象在運行的時候,需要處理無法預測的事情,諸如用戶點了下屏幕,用戶點了下按鈕,輸入點東西,或者需要從網絡發送接收數據之類的。后來,引入了泛型的概念之后,類也開始不明確了,如果使用了泛型,直到程序運行的時候,才知道究竟是哪種對象需要處理。 對象可以很復雜,也可以跟時序相關。一般來說,“活的”對象只生存在內存里,關機斷電就沒有了。一般來說,“活的”對象只能由本地的進程使用,不能被發送到網絡上的另外一臺計算機。 序列化,可以存儲“活的”對象,可以將“活的”對象發送到遠程計算機。 把“活的”對象序列化,就是把“活的”對象轉化成一串字節,而“反序列化”,就是從一串字節里解析出“活的”對象。于是,如果想把“活的”對象存儲到文件,存儲這串字節即可,如果想把“活的”對象發送到遠程主機,發送這串字節即可,需要對象的時候,做一下反序列化,就能將對象“復活”了。 將對象序列化存儲到文件,術語又叫“持久化”。將對象序列化發送到遠程計算機,術語又叫“數據通信”。 java對序列化提供了非常方便的支持,在定義類的時候,如果想讓對象可以被序列化,只要在類的定義上加上了”implements Serializable”即可,比如說,可以這么定義”public class Building implements Serializable”,其他什么都不要做,Java會自動的處理相關一切。Java的序列化機制相當復雜,能處理各種對象關系。 Java的序列化機制的缺點就是計算量開銷大,且序列化的結果體積大太,有時能達到對象大小的數倍乃至十倍。它的引用機制也會導致大文件不能分割的問題。這些缺點使得Java的序列化機制對Hadoop來說是不合適的。于是Hadoop設計了自己的序列化機制。 為什么序列化對Hadoop很重要?因為Hadoop在集群之間進行通訊或者RPC調用的時候,需要序列化,而且要求序列化要快,且體積要小,占用帶寬要小。所以必須理解Hadoop的序列化機制。
2. Hadoop的序列化接口 什么是接口?簡答來說,接口就是規定,它規定類必須實現的方法。一個接口可以包含多干個方法。如果一個類說自己實現了某個接口,那么它必須實現這個接口里的所有方法。特殊情況下,接口也可以沒有任何方法。 Writable接口,也就是org.apache.hadoop.io.Writable接口。Hadoop的所有可序列化對象都必須實現這個接口。Writable接口里有兩個方法,一個是write方法,將對象寫入字節流,另一個是readFields方法,從字節流解析出對象。 Java的API提供了Comparable接口,也就是java.lang.Comparable接口。這個接口只有一個方法,就是compareTo,用于比較兩個對象。 WritableComparable接口同時繼承了Writable和Comparable這兩個接口。 Hadoop里的三個類IntWritable、DoubleWritable和ByteWritable,都繼承了WritableComparable接口。注意,IntWritable、DoubleWritable和ByteWritable,盡管后綴是“Writable”,但它們不是接口,是類!! Hadoop的序列化接口還有更多的類型,在這里不一一列舉。
3. IntWritable如何序列化3.1 目錄和文件結構 這個例子演示IntWritable如何序列化。首先,創建一個IntWritable,然后,將它序列化,輸出到一個字節流中。然后,創建一個新的IntWritable,從字節流中讀取值,這是反序列化。 創建目錄~/intser存放源代碼、編譯和打包結果。在intser目錄下,有兩個子目錄,分別是src目錄和classes目錄,src目錄存放Java源代碼,class存放編譯結果。在src目錄下,只有一個源代碼文件IntSer.java。3.2 IntSer.java文件的源代碼

package com.brianchen.hadoop;import java.io.DataOutputStream;import java.io.DataInputStream;import java.io.ByteArrayOutputStream;import java.io.ByteArrayInputStream;import java.io.IOException;import org.apache.hadoop.io.Writable;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.util.StringUtils;public class IntSer{    public byte[] serialize(Writable w)throws IOException{    ByteArrayOutputStream out = new ByteArrayOutputStream();    DataOutputStream dataout = new DataOutputStream(out);    w.write(dataout);    dataout.close();    return out.toByteArray();  }    public byte[] deserialize(Writable w, byte[] bytes) throws IOException{    ByteArrayInputStream in = new ByteArrayInputStream(bytes);    DataInputStream datain = new DataInputStream(in);    w.readFields(datain);    datain.close();    return bytes;  }    public static void main(String[] args) throws Exception{    IntWritable intw = new IntWritable(7);    byte[] bytes = serialize(intw);    String bytes_str = StringUtils.byteToHexString(bytes);    System.out.PRintln(bytes_str);    IntWritable intw2 = new IntWritable(0);    deserialize(intw2, bytes);    System.out.println(intw2);  }}
3.3 編譯    “cd ~/intser”    “javac -cp /home/brian/usr/hadoop/hadoop-1.2.1/hadoop-core-1.2.1.jar -d ./classes src/*.java”3.4 打包    “jar -cvf intser.jar -C ./classes .”3.5 運行    “cd ~/usr/hadoop/hadoop-1.2.1”    “./bin/hadoop jar /home/brian/intser/intser.jar com.brianchen.hadoop.IntSer”    首先確認Hadoop已經是運行的,然后切換到Hadoop的安裝目錄,然后運行,輸出結果是兩行,第一行是”00000007”,第二行是”7”。
新聞熱點
疑難解答