當前位置:
首頁 > 知識 > 如何在MapReduce中使用SequenceFile數據格式?

如何在MapReduce中使用SequenceFile數據格式?

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

3.3.2 SequenceFile

因為SequenceFile是為與MapReduce一起使用而創建的,所以這種格式可以說是與MapReduce、Pig和Hive一起提供最高級別集成支持的數據格式。SequenceFile是一種可拆分的二進位文件格式,以Key/value形式存儲數據。所有SequenceFiles共享相同的頭格式,如圖3.8所示。

如何在MapReduce中使用SequenceFile數據格式?

圖3.8 SequenceFile頭格式

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

Uncompressed

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

Record-compressed

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

如何在MapReduce中使用SequenceFile數據格式?

圖3.9 record-compressed和uncompressed SequenceFiles的

Block-compressed(塊壓縮)

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

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

如何在MapReduce中使用SequenceFile數據格式?

圖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類並定義序列化和反序列化方法,如下所示。

如何在MapReduce中使用SequenceFile數據格式?

列表3.3 表示stock price的寫實現

現在有了Writable,你需要編寫一些代碼來創建SequenceFile。我們可以從本地磁碟讀取stocks文件,創建StockWritable,並使用stock price作為密鑰將其寫入SequenceFile:

如何在MapReduce中使用SequenceFile數據格式?

如何讀並創建寫文件?

如何在MapReduce中使用SequenceFile數據格式?

現在需要通過寫和讀文件來證明其工作原理:

如何在MapReduce中使用SequenceFile數據格式?

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

如何在MapReduce中使用SequenceFile數據格式?

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

如何在MapReduce中使用SequenceFile數據格式?

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

如何在MapReduce中使用SequenceFile數據格式?

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

如何在MapReduce中使用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非常簡單,如下所示:


如何在MapReduce中使用SequenceFile數據格式?

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

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

如何在MapReduce中使用SequenceFile數據格式?

Hive

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

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


如何在MapReduce中使用SequenceFile數據格式?

總結

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寫入輸出流並從輸入流中讀取它們的方法,如下面的代碼所示:

如何在MapReduce中使用SequenceFile數據格式?

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


如何在MapReduce中使用SequenceFile數據格式?


如何在MapReduce中使用SequenceFile數據格式?

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

如何在MapReduce中使用SequenceFile數據格式?


如何在MapReduce中使用SequenceFile數據格式?


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


如何在MapReduce中使用SequenceFile數據格式?

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


如何在MapReduce中使用SequenceFile數據格式?


如何在MapReduce中使用SequenceFile數據格式?

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


如何在MapReduce中使用SequenceFile數據格式?

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

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT168企業級 的精彩文章:

真假路由「易混淆」 斐訊K系列「做典範」
回顧&展望:殺毒軟體的「前世今生」

TAG:IT168企業級 |