如何在MapReduce中使用SequenceFile資料格式?

趙鈺瑩發表於2018-09-19

本文作為《Hadoop從入門到精通》大型專題的第三章第三節,主要介紹如何在MapReduce中使用SequenceFile資料格式。我們在上一篇文章中提到了許多可與MapReduce大資料處理匹配的資料格式,本節將首先介紹SequenceFile資料格式。(往期文章可自行檢視文末連結)

3.3.2  SequenceFile

因為SequenceFile是為與MapReduce一起使用而建立的,所以這種格式可以說是與MapReduce、Pig和Hive一起提供最高階別整合支援的資料格式。SequenceFile是一種可拆分的二進位制檔案格式,以Key/value形式儲存資料。所有SequenceFiles共享相同的頭格式,如圖3.8所示。

 

圖3.8 SequenceFile頭格式

SequenceFiles有三種型別,根據應用壓縮的方式而有所不同,每種型別都有自己對應的Writer類。

Uncompressed

Uncompressed SequenceFiles是使用SequenceFile.Writer類編寫的,其對比壓縮格式並沒有任何優勢,因為壓縮通常會減少儲存佔用空間,並且對讀取和寫入更有效,如圖3.9所示。

Record-compressed

Record-compressed SequenceFiles是使用SequenceFile.RecordCompressWriter類編寫的。記錄新增到SequenceFile後會立即被壓縮並寫入該檔案。這種方法的缺點是與塊壓縮相比,壓縮比略有不同。該檔案格式與uncompressed SequenceFiles基本相同,如圖3.9所示。

 

圖3.9  record-compressed和uncompressed SequenceFiles的檔案格式

Block-compressed(塊壓縮)  

Block-compressed SequenceFiles是使用SequenceFile.BlockCompressWriter類編寫的。預設情況下,塊大小與HDFS塊大小相同,但可以覆蓋它,這種壓縮的優勢在於壓縮程度更容易達到理想狀態。整個塊被壓縮,而不是在記錄級別壓縮。直到達到塊大小才寫入資料,此時整個塊被壓縮,從而產生良好的整體壓縮狀態。如圖3.10所示。

你只需要一個Reader類(SequenceFile.Reader)讀取所有三種型別的SequenceFiles。甚至Writer也是抽象的,因為你可以呼叫SequenceFile.createWriter決定首選格式,並且返回一個基類,無論如何壓縮都可以用於寫入。

 

圖3.10 塊壓縮的SequenceFile格式

SequenceFiles具有可插入的序列化框架,寫入的key和value必須具有相關的org.apache.hadoop.io.serializer.Serializer和Deserializer,用於編組和解組。Hadoop附帶了四個序列化程式:Avro,Java,Tether(用於TetherData類中包含的二進位制資料)和Writable(預設序列化程式)。

自定義SequenceFile序列化

如果希望SequenceFile包含可序列化物件,則需要實現自己的Serializer並註冊,可以透過更新core-site.xml並將自定義序列化實現的類名追加到io.serializations屬性來註冊。

SequenceFiles是可拆分的,因為對於 record-based檔案而言,每個檔案大約每6 KiB(1 kibibyte = 1024位元組)就會寫入一個同步標記,並且在每個塊之前寫入基於塊的檔案。

現在讓我們看一下如何在MapReduce中使用SequenceFiles。

如何使用SequenceFiles?

當必須支援複雜型別資料時,使用MapReduce中的文字會變得很棘手,這些資料可能包括nonscalar的資料型別,如列表或詞典。此外,如果MapReduce的資料位置屬性很重要,那麼大型壓縮文字檔案需要一些額外的考慮,但使用SequenceFile等檔案格式可以克服這些挑戰。

問題

希望在MapReduce中使用結構化檔案格式,可以使用該格式模擬複雜資料結構,並且支援壓縮和可拆分輸入。

解決方案

該技術著眼於如何從獨立應用程式和MapReduce中使用SequenceFile檔案格式。

討論

SequenceFile格式提供與MapReduce等工具的高度整合,還可以對複雜資料結構進行建模。我們將研究如何讀取和編寫SequenceFiles,以及如何將它們與MapReduce、Pig和Hive一起使用。

我們將使用此技術的庫存資料。與SequenceFiles一起使用的最常見序列化方法是Writable,因此需要建立一個Writable來表示stock資料。編寫複雜Writable的關鍵元素是擴充套件Writable類並定義序列化和反序列化方法,如下所示。

 

列表3.3 表示stock price的寫實現

 

現在有了Writable,你需要編寫一些程式碼來建立SequenceFile。我們可以從本地磁碟讀取stocks檔案,建立StockWritable,並使用stock price作為金鑰將其寫入SequenceFile:

   

如何讀並建立寫檔案?

 

現在需要透過寫和讀檔案來證明其工作原理:

 

我們將如何在MapReduce中處理此SequenceFile?幸運的是,SequenceFileInputFormat和SequenceFileOutputFormat都與MapReduce很好地整合。因為Writable是MapReduce中的本機資料格式,所以使用帶有MapReduce的SequenceFiles是完全透明的。以下程式碼顯示了帶有mapper和reducer的MapReduce作業:

 

現在,你可以針對先前建立的stocks SequenceFile執行MapReduce作業:

 

因為我們所做的只是回顯輸出的輸入,所以應該在兩個檔案中看到相同的內容,可以透過讀取作業輸出檔案來確保這種情況。至於如何驗證輸出是否為SequenceFile,很簡單,SequenceFile輸出的前三個位元組是SEQ,然後是包含SequenceFile版本的第四個位元組,然後是key和value類:

 

現在嘗試使用之前編寫的SequenceFile讀取器程式碼將其轉儲到標準輸出:

 

因為SequenceFiles是基於key/value的,並且SequenceFiles的預設序列化資料格式是可寫的,所以使用SequenceFiles對於map和reduce完全透明。我們透過使用MapReduce的內建map和 reduce類並使用SequenceFile作為輸入證明了這一點。 我們唯一需要做的就是告訴MapReduce使用特定於SequenceFile的輸入和輸出格式類,這些類都構建在MapReduce中。

在Pig中讀取SequenceFiles

如果自己編寫Writable,可以使用非MapReduce工具(如Pig)建立更多工作。Pig適用於Hadoop的內建scalar Writable,如Text和IntWritable,但不支援自定義Writable。 你需要編寫自己的LoadFunc來支援StockPriceWritable。這適用於MapReduce,但Pig的SequenceFileLoader不能與自定義Writable一起使用,這意味著需要編寫自己的Pig載入程式來處理檔案。LoadFunc for Pig非常簡單,如下所示:

列表3.4 一個Pig載入器函式,將StockPriceWritable轉換為Pig元組

現在可以嘗試在Pig中載入和轉儲stock SequenceFile:

 

Hive

Hive包含對SequenceFiles的內建支援,但它有兩個限制。首先,它忽略了每條記錄的關鍵部分。其次,開箱即用只適用於可寫的SequenceFile值,透過執行toString()將值轉換為Text形式來支援。

如果有自定義Writable,則必須編寫一個Hive SerDe,它將Writable反序列化為Hive可以理解的形式。生成的DDL語句如下:

 

總結

SequenceFiles非常有用,因為其解決了MapReduce最具挑戰性的問題——其本身可拆分且具有內建壓縮支援,這使得它對使用者完全透明。當然,它們也可用作其他檔案格式的容器,如果這些格式不能整合到MapReduce中。SequenceFiles比較棘手的是缺乏多語言支援,限制了與資料互操作的工具範圍。但是,如果資料大部分保留在HDFS中並使用MapReduce(或Hive / Pig)進行處理,那麼SequenceFiles可能是你所需要的。

SequenceFiles的另一個挑戰是在使用Writable時缺乏模式演變 - 對Writable進行更改不會向後或向前相容,除非將其構建到實現中。這可以透過使用Protocol Buffers作為key/value型別來解決。

該技術研究瞭如何將SequenceFiles與Writable一起使用,SequenceFile知道如何在其檔案格式內進行編碼和解碼。如何透過SequenceFiles使用Writables以外的資料?

使用SequenceFiles編碼Protocol Buffers

Writable是SequenceFiles中的一等公民,並且API具有讀取和寫入Writable例項的特定方法,這並不意味著SequenceFiles僅限於使用Writables。事實上,只要有一個插入Hadoop序列化框架的資料型別的序列化實現,就可以使用任何資料型別。

Protocol Buffers是Google開源的複雜資料格式,提供了模式演變和高效資料編碼功能。 (有關Protocol Buffers的更多詳細資訊,請參見之後的第3.3.3節)。在這種技術中,我們可以實現Protocol Buffers序列化,並瞭解如何在MapReduce中使用本機Protocol Buffers物件。

問題

希望在MapReduce中使用Protocol Buffers資料。

解決方案

編寫Protocol Buffers序列化程式,使能夠在SequenceFiles中編碼Protocol Buffers序列化資料。

討論

出於效能考慮,Hadoop使用自己的框架來序列化和反序列化資料。此框架的一個示例用法是將map輸出作為shuffle階段的一部分寫入磁碟,所有map輸出必須具有相應的Hadoop序列化類,該類知道如何讀取和寫入資料流。Writable是MapReduce中最常用的資料型別,有一個WritableSerialization類且使用Writable介面上的readFields和writeFields方法執行序列化。

SequenceFiles使用相同的序列化框架來序列化和反序列化其key/value記錄中的資料,這就是SequenceFiles開箱即用支援Writable的原因。因此,將資料型別編碼到SequenceFile只是編寫自己的Hadoop序列化例項問題。

 Protocol Buffers與SequenceFiles一起使用的第一步是編寫自己的序列化類。每個序列化類都必須支援序列化和反序列化,所以從序列化器開始,其作用是將記錄寫到輸出流。

以下程式碼使用MessageLite類作為type,是所有生成的Protocol Buffers類的超類。MessageLite介面提供了將Protocol Buffers寫入輸出流並從輸入流中讀取它們的方法,如下面的程式碼所示:

 

接下來是解串器,其作用是從輸入流填充Protocol Buffers物件。與序列化相比,Protocol Buffers物件只能透過其 builder類進行構建:

 

現在,我們需要配置Hadoop序列化框架以使用新的序列化程式。這是透過將新的序列化程式附加到io.serializations屬性來完成的。編寫輔助方法通常可以使客戶端變得容易。以下示例顯示了與Hadoop 2捆綁在一起的標準序列化程式,它們附加了剛剛建立的序列化類。這裡沒有顯示ProtobufSerialization的原始碼,它只是返回ProtobufSerializer和ProtobufDeserializer例項: 

 

接下來,需要生成一個新的Protocol Buffers編碼的SequenceFile。這裡的關鍵項是在使用SequenceFile writer之前呼叫register方法(如前面的程式碼所示):

 

關於MapReduce程式碼,新的序列化程式的優點是map和reduce類可以直接使用Protocol Buffers物件。同樣,關鍵在於如何配置作業以使Protocol Buffers序列化程式可用。在下面的示例中,使用標識函式來演示如何在SequenceFiles中編碼:

 

現在,你可以編寫具有Protocol Buffers值的SequenceFile,對該資料執行標識MapReduce作業,然後轉儲作業輸出內容:

 

以上是本章節的所有內容,在下一章節,我們將研究可以將Protocol Buffers整合到MapReduce中的其他方法。

相關文章:

1、《第一章:Hadoop生態系統及執行MapReduce任務介紹!》連結:   http://blog.itpub.net/31077337/viewspace-2213549/

2、《學習Hadoop生態第一步:Yarn基本原理和資源排程解析!》連結:   http://blog.itpub.net/31077337/viewspace-2213602/

3、《MapReduce如何作為Yarn應用程式執行?》連結:   http://blog.itpub.net/31077337/viewspace-2213676/

4、《Hadoop生態系統各元件與Yarn的相容性如何?》連結:   http://blog.itpub.net/31077337/viewspace-2213960/

5、《MapReduce資料序列化讀寫概念淺析!》連結:  http://blog.itpub.net/31077337/viewspace-2214151/

6、《MapReuce中對大資料處理最合適的資料格式是什麼?》連結: http://blog.itpub.net/31077337/viewspace-2214325/

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31077337/viewspace-2214505/,如需轉載,請註明出處,否則將追究法律責任。

相關文章