注:本文涉及書(shū)中4.3小結(jié)
序列化與反序列化
1. 定義
序列化(serialization):將結(jié)構(gòu)化對(duì)象轉(zhuǎn)化為字節(jié)流。
反序列化(deserialization):將字節(jié)流轉(zhuǎn)回結(jié)構(gòu)化對(duì)象的逆過(guò)程。
2. 應(yīng)用場(chǎng)景
序列化在分布式數(shù)據(jù)處理的兩大領(lǐng)域經(jīng)常出現(xiàn):進(jìn)程間通信和永久存儲(chǔ)。
在Hadoop中,多個(gè)節(jié)點(diǎn)上的進(jìn)程間通信是通過(guò)RPC(遠(yuǎn)程過(guò)程調(diào)用)實(shí)現(xiàn)的。RPC協(xié)議將消息序列化成二進(jìn)制流后發(fā)送到遠(yuǎn)程節(jié)點(diǎn),遠(yuǎn)程節(jié)點(diǎn)再將二進(jìn)制流反序列化為原始消息。
Hadoop使用序列化格式Wriable,這是Hadoop的核心。
補(bǔ)充
在Hadoop中,Mapper,Combiner,Reducer等階段之間的通信都需要使用序列化與反序列化技術(shù)。舉例來(lái)說(shuō),Mapper產(chǎn)生的中間結(jié)果(<key: value1, value2, ···>)需要寫(xiě)入到本地硬盤(pán),這是序列化過(guò)程(將結(jié)構(gòu)化對(duì)象轉(zhuǎn)化為字節(jié)流,并寫(xiě)入硬盤(pán)),而Reducer階段讀取Mapper的中間結(jié)果的過(guò)程則是一個(gè)反序列化過(guò)程(讀取硬盤(pán)上存儲(chǔ)的字節(jié)流文件,并轉(zhuǎn)回為結(jié)構(gòu)化對(duì)象),需要注意的是,能夠在網(wǎng)絡(luò)上傳輸?shù)闹荒苁亲止?jié)流,Mapper的中間結(jié)果在不同主機(jī)間洗牌時(shí),對(duì)象將經(jīng)歷序列化和反序列化兩個(gè)過(guò)程。
序列化是Hadoop核心的一部分,在Hadoop中,位于org.apache.hadoop.io包中的Writable接口是Hadoop序列化格式的實(shí)現(xiàn)。
Writable接口
Writable接口定義了兩個(gè)方法:
1. 狀態(tài)寫(xiě):將其狀態(tài)寫(xiě)到DataOutput二進(jìn)制流。
2. 狀態(tài)讀:DataOutput二進(jìn)制流讀取狀態(tài)。
WritableComparable接口和comparator
補(bǔ)充
書(shū)中說(shuō)的不太明白,故自己比較一下:Comparable接口 VS Comparator接口
在?“?集合框架?”?中有兩種比較接口:?Comparable?接口和?Comparator?接口。?Comparable?是通用的接口,用戶可以實(shí)現(xiàn)它來(lái)完成自己特定的比較,而?Comparator?可以看成一種算法的實(shí)現(xiàn),在需要容器集合實(shí)現(xiàn)比較功能的時(shí)候,來(lái)指定這個(gè)比較器,這可以看成一種設(shè)計(jì)模式,將算法和數(shù)據(jù)分 離。前者應(yīng)該比較固定,和一個(gè)具體類相綁定;而后者比較靈活,它可以被用于各個(gè)需要比較功能的類使用。
一個(gè)類實(shí)現(xiàn)了?Camparable?接口表明這個(gè)類的對(duì)象之間是可以相互比較的。如果用數(shù)學(xué)語(yǔ)言描述的話就是這個(gè)類的對(duì)象組成的集合中存在一個(gè)全序。這樣,這 個(gè)類對(duì)象組成的集合就可以使用?Sort?方法排序了。
而?Comparator?的作用有兩個(gè):
1?、如果類的設(shè)計(jì)師沒(méi)有考慮到?Compare?的問(wèn)題而沒(méi)有實(shí)現(xiàn)?Comparable?接口,可以通過(guò)?Comparator?來(lái)實(shí)現(xiàn)比較算法進(jìn)行排序;
2?、為了使用不同的排序標(biāo)準(zhǔn)做準(zhǔn)備,比如:升序、降序或其他什么序。
Writable類
Hadoop自身提供了多種具體的Writable類,封裝了常見(jiàn)的Java基本類型(boolean、byte、short、int、float、long和double等)和集合類型(BytesWritable、ArrayWritable和MapWritable等)。這些類型都位于org.apache.hadoop.io包中。
1. Java基本類型的Writable封裝器
所有的封裝包含get()和set()兩種方法,用于讀取和存儲(chǔ)封裝的值。
2. Text類型
Text是針對(duì)UTF-8序列的Writable類。
Text類型的索引、迭代、可變性、對(duì)String重新排序,詳見(jiàn)書(shū)4.3.2小節(jié)。
書(shū)中還有:Text與String的比較
3. BytesWritable
BytesWritable是對(duì)二進(jìn)制數(shù)據(jù)數(shù)組的封裝。
它的序列化格式為:一個(gè)指定所含數(shù)據(jù)字節(jié)數(shù)的整數(shù)域(4字節(jié),即8bit),后跟數(shù)據(jù)內(nèi)容本身。
4. NullWritable
NullWritable是Writable的特殊類型,它的序列化長(zhǎng)度為0,既不從數(shù)據(jù)流中讀取數(shù)據(jù),也不寫(xiě)入數(shù)據(jù),充當(dāng)占位符。
5. ObjectWritable和GenericWritable
ObjectWritable是對(duì)Java基本類型(String, enum, Writable, null或這些類型組成的數(shù)組)的一個(gè)通用封裝。它在Hadoop RPC中用于對(duì)方法的參數(shù)和返回類型進(jìn)行封裝和解封裝。當(dāng)一個(gè)字段包含多種類型時(shí),ObjectWritable非常有用。
Objectwritable?作為一個(gè)通用機(jī)制,這是相當(dāng)浪費(fèi)空間的,因?yàn)槊看嗡恍蛄谢猓家獙?xiě)入被封裝類型的類名。GenericWritable 對(duì)此做出了改進(jìn),如果類型的數(shù)量不多并且事先可知,那么可以使用一個(gè)靜態(tài)類型數(shù)組來(lái)提高效率,使用數(shù)組的索引來(lái)作為類型的序列化引用.這是GenericWritable?使用的方法,我們必須繼承它以指定支持的類型。
6. Writable集合類
共有6個(gè)Writable集合類:
(1)+(2)ArrayWritable和TwoDArrayWritable
它們是對(duì)Writable的數(shù)組和二維數(shù)組的實(shí)現(xiàn)。常用函數(shù)包括toArray()、get()、set()
(3)ArrayPrimitiveWritable
對(duì)Java基本數(shù)組類型的一個(gè)封裝。
(4)+(5)+(6)MapWritable,SortedMapWritable,EnumMapWritable
MapWritable:對(duì)集合和列表,枚舉集合中的元素
SortedMapWritable:針對(duì)排序集合,枚舉集合中的元素
EnumMapWritable:對(duì)集合的枚舉類型采用EnumMapWritable
補(bǔ)充
AbstractMapWritable作為MapWritable抽象類并沒(méi)有涉及到Map的鍵值對(duì)操作,而是從抽象層抽象出索引表,其實(shí)現(xiàn)類MapWritable和SortedMapWritable則是新增了Map變量,不同的之處在于SortedMapWritable是實(shí)現(xiàn)了排序了的TreeMap,自身已具有排序功能。
定制的Writable集合
書(shū)中范例4-7實(shí)現(xiàn)了存儲(chǔ)一對(duì)Text對(duì)象的Writable
序列化框架
大部分的MapReduce程序都使用Writable鍵–值對(duì)作為輸入和輸出,但這并不是Hadoop強(qiáng)制使用的,其他序列化機(jī)制也能和Hadoop配合,并應(yīng)用于MapReduce中。
目前,除了前面介紹過(guò)的Java序列化機(jī)制和Hadoop使用的Writable機(jī)制,還流行其他序列化框架,如Hadoop Avro、Apache Thrift和Google Protocol Buffer。
1. 序列化框架(Serialization)
MapReduce僅僅可以支持Writable做key,value嗎?答案是否定的。事實(shí)上,可以使用任何類型:只要能有一種機(jī)制能對(duì)每個(gè)類型進(jìn)行類型與二進(jìn)制表示的來(lái)回轉(zhuǎn)換。為此Hadoop提供了一個(gè)針對(duì)序列化做替換的框架來(lái)支持,他們?cè)趏rg.apache.hadoop.io.serializer包中,Writable可以作為MapReduce支持的類型也是因?yàn)閷?shí)現(xiàn)了這個(gè)框架,類不多,我們從幾個(gè)接口說(shuō)起。
Hadoop提供了一個(gè)簡(jiǎn)單的序列化框架API,用于集成各種序列化實(shí)現(xiàn),該框架由Serialization實(shí)現(xiàn)(在org.apache.hadoop.io.serializer包中)。
2. 序列化IDL
還有許多其他序列化框架從不同的角度來(lái)解決該問(wèn)題:即不通過(guò)代碼來(lái)定義類型,而是使用IDL(Interface Description Language, 接口定義語(yǔ)言)以不依賴于具體語(yǔ)言的方式進(jìn)行聲明。