Hadoop序列化與Writable接口(一)
Hadoop序列化與Writable接口(一)
序列化
序列化(serialization)是指將結構化的對象轉化為字節流,以便在網絡上傳輸或者寫入到硬盤進行永久存儲;相對的反序列化(deserialization)是指將字節流轉回到結構化對象的過程。
在分布式系統中進程將對象序列化為字節流,通過網絡傳輸到另一進程,另一進程接收到字節流,通過反序列化轉回到結構化對象,以達到進程間通信。在Hadoop中,Mapper,Combiner,Reducer等階段之間的通信都需要使用序列化與反序列化技術。舉例來說,Mapper產生的中間結果(<key: value1, value2...>
序列化是Hadoop核心的一部分,在Hadoop中,位於org.apache.hadoop.io包中的Writable接口是Hadoop序列化格式的實現。
Writable接口
Hadoop Writable接口是基於DataInput和DataOutput實現的序列化協議,緊湊(高效使用存儲空間),快速(讀寫數據、序列化與反序列化的開銷小)。Hadoop中的鍵(key)和值(value)必須是實現了Writable接口的對象(鍵還必須實現WritableComparable,以便進行排序)。
以下是Hadoop(使用的是Hadoop 1.1.2)中Writable接口的聲明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
|
Writable類
Hadoop自身提供了多種具體的Writable類,包含了常見的Java基本類型(boolean、byte、short、int、float、long和double等)和集合類型(BytesWritable、ArrayWritable和MapWritable等)。這些類型都位於org.apache.hadoop.io包中。
(圖片來源:safaribooksonline.com)
定制Writable類
雖然Hadoop內建了多種Writable類提供用戶選擇,Hadoop對Java基本類型的包裝Writable類實現的RawComparable接口,使得這些對象不需要反序列化過程,便可以在字節流層面進行排序,從而大大縮短了比較的時間開銷,但是當我們需要更加復雜的對象時,Hadoop的內建Writable類就不能滿足我們的需求了(需要註意的是Hadoop提供的Writable集合類型並沒有實現RawComparable接口,因此也不滿足我們的需要),這時我們就需要定制自己的Writable類,特別將其作為鍵(key)的時候更應該如此,以求達到更高效的存儲和快速的比較。
下面的實例展示了如何定制一個Writable類,一個定制的Writable類首先必須實現Writable或者WritableComparable接口,然後為定制的Writable類編寫write(DataOutput out)和readFields(DataInput in)方法,來控制定制的Writable類如何轉化為字節流(write方法)和如何從字節流轉回為Writable對象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
|