MapReduce資料序列化讀寫概念淺析!

趙鈺瑩發表於2018-09-13

MapReduce為處理簡單資料格式(如日誌檔案)提供了簡明的文件支援,但MapReduce已經從日誌檔案發展到更復雜的資料序列化格式(如文字,XML和JSON)處理,本章的目標是記錄如何使用常見的資料序列化格式,以及檢查更結構化的序列化格式,並比較它們與MapReduce的適用性。本文作為《Hadoop從入門到精通》大型專題第3章第一節,主要介紹了MapReduce處理以不同格式(如XML和JSON)儲存資料的方法,為更深入瞭解Avro和Parquet等這類適合大資料和Hadoop的資料格式鋪平了道路。

資料序列化 - 使用文字及其他方法

如果希望使用無處不在的XML和JSON資料序列化格式,這些格式在大多數程式語言中都可直接工作,有多種工具可用於編組、解組和驗證。但是,在MapReduce中使用XML和JSON面臨兩大挑戰。首先,MapReduce需要能夠支援讀寫特定資料序列化格式的類,如果想使用自定義檔案格式,那麼很可能沒有相應的類支援正在使用的序列化格式;其次,MapReduce的強大之處在於能夠並行讀取輸入資料,如果輸入檔案很大(數百兆位元組甚至更多),讀取序列化格式的類能夠將較大檔案拆分以便多個任務可以並行讀取,這一點至關重要。

本章將從解決如何使用XML和JSON等序列化格式問題開始,將比較更適合處理大資料的資料序列化格式,例如Avro和Parquet,並解答當需要使用專有或不常見的檔案格式時應該如何編碼。本文作為第三章的第一節將主要介紹一些基本概念。

XML和JSON格式

MapReduce中的資料序列化支援是讀取和寫入MapReduce資料輸入和輸出類屬性,讓我們首先概述MapReduce如何支援資料輸入和輸出。

3.1 瞭解MapReduce中的輸入和輸出

你的資料可能位於許多FTP伺服器後面的XML檔案、中央Web伺服器上的文字日誌檔案或HDFS中的Lucene索引。MapReduce如何跨多種儲存機制讀取和寫入這些不同的序列化結構?

圖3.1 MapReduce中的輸入和輸出actor

圖3.1顯示了通過MapReduce的資料流,並確定了負責流的各部分參與者。在輸入端,我們可以看到某些工作(建立拆分)在map階段以外執行,而其他工作則作為map階段的一部分執行(讀取拆分),所有輸出工作都在reduce階段(寫輸出)執行。

圖3.2 顯示了僅使用map作業的相同流程,在僅map作業中,MapReduce框架仍使用OutputFormat和RecordWriter類將輸出直接寫入資料接收器。讓我們來看看資料流並討論各角色的責任,我們還將檢視內建TextInputFormat和TextOutputFormat類中的相關程式碼,以更好地理解這些概念,TextInputFormat和TextOutputFormat類讀取和寫入面向行的文字檔案。

3.1.1資料輸入支援

MapReduce中資料輸入的兩個類是InputFormat和RecordReader,查詢InputFormat類以確定應如何為map任務分割槽輸入資料,並且RecordReader執行從輸入讀取資料。

INPUTFORMAT

MapReduce中的每個作業都必須根據InputFormat抽象類中指定的規則定義其輸入。InputFormat實現者必須完成三步:描述map輸入鍵和值型別資訊;指定輸入資料應該如何分割槽;指示應該從源讀取資料的RecordReader例項。

圖3.2沒有Reducer的MapReduce輸入和輸出actor

圖3.3帶註釋的InputFormat類及其三個規則

可以說,最重要的規則是確定如何劃分輸入資料。在MapReduce命名法中,這些劃分稱為輸入拆分。輸入拆分直接影響map並行效率,因為每個拆分由單個map任務處理。 使用無法在單個資料來源(例如檔案)上建立多個輸入拆分的InputFormat將導致map階段進行緩慢,因為將會按順序處理該檔案。

TextInputFormat類提供了InputFormat類的createRecordReader方法實現,但它將輸入拆分的計算委託給其父類FileInputFormat。以下程式碼顯示了TextInputFormat類的相關部分:

 

確定輸入拆分的FileInputFormat程式碼稍微複雜,以下示例顯示了程式碼的簡化形式,以描述getSplits方法的主要元素:

以下程式碼顯示瞭如何指定用於MapReduce作業的InputFormat:

job.setInputFormatClass(TextInputFormat.class);

RECORDREADER

我們將在map任務中建立和使用RecordReader類,以從輸入拆分中讀取資料,並以 key/value形式提供每個記錄供mapper使用。通常為每個輸入拆分建立一個任務,每個任務都有一個RecordReader,負責讀取該輸入拆分的資料。

圖3.4 帶註釋的RecordReader類及其抽象方法

如前所示,TextInputFormat類建立一個LineRecordReader以從輸入拆分中讀取記錄。LineRecordReader直接擴充套件RecordReader類,並使用LineReader類從輸入拆分中讀取行。LineRecordReader使用檔案中的位元組偏移量作為map key,並使用行的內容作為map value。 以下示例顯示了LineRecordReader的簡化版本:

因為LineReader類很簡單,所以我們將跳過該程式碼。下一步是檢視MapReduce如何支援資料輸出。

3.1.2 資料輸出

MapReduce使用與輸入類似的過程來支援輸出資料。必須存在兩個類:OutputFormat和RecordWriter。OutputFormat執行資料接收器屬性的一些基本驗證,RecordWriter將每個reducer輸出寫入資料接收器。

OUTPUTFORMAT

與InputFormat類非常相似,OutputFormat類(如圖3.5所示)定義了實現必須滿足的條件:檢查與作業輸出相關的資訊;提供RecordWriter並指定輸出提交者;允許寫入並在任務完成時保持“permanent”。

圖3.5 帶註釋的OutputFormat類

就像TextInputFormat一樣,TextOutputFormat還擴充套件了一個基類FileOutputFormat,負責複雜的資料流操作,例如輸出提交。接下來,我們來看看TextOutputFormat執行工作流程,以下程式碼顯示瞭如何指定用於MapReduce作業的OutputFormat:

job.setOutputFormatClass(TextOutputFormat.class);

RECORDWRITER

我們將使用RecordWriter將reducer輸出寫入目標資料接收器。這是一個簡單的類,如圖3.6所示。

TextOutputFormat返回一個LineRecordWriter物件,它是TextOutputFormat的內部類,用於執行對檔案寫入,以下示例顯示了該類的簡化版本:

在map端,InputFormat可確定執行了多少個map任務;在reducer端,任務的數量完全基於客戶端設定的mapred.reduce.tasks值(如果沒有設定, 該值會從mapred-site.xml中獲取,如果站點檔案中不存在,則從mapred-default.xml獲取)。

以上是在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/

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

相關文章