MapReduce中對大資料處理最合適的資料格式是什麼?

趙鈺瑩發表於2018-09-17

在本章的第一章節介紹中,我們簡單瞭解了Mapreduce資料序列化的概念,以及其對於XML和JSON格式並不友好。本節作為《Hadoop從入門到精通》大型專題的第三章第二節將教大家如何在Mapreduce中使用XML和JSON兩大常見格式,並分析比較最適合Mapreduce大資料處理的資料格式。(本專題的其他章節閱讀詳見文末連結)

3.2.1 XML 

XML自1998年誕生以來就作為一種資料格式來表示機器和人類都可讀的資料。它成為系統之間資料交換的通用語言,現在被許多標準所採用,例如SOAP和RSS,並且被用作Microsoft Office等產品的開放資料格式。

MapReduce和XML

MapReduce捆綁了與文字一起使用的InputFormat,但沒有支援XML,也就是說,原生Mapreduce對XML十分不友好。在MapReduce中並行處理單個XML檔案很棘手,因為XML不包含其資料格式的同步標記。

問題

希望在MapReduce中使用大型XML檔案,並能夠並行拆分和處理。

解決方案

Mahout的XMLInputFormat可用於MapReduce處理HDFS中的XML檔案。 它讀取由特定XML開始和結束標記分隔的記錄,此技術還解釋瞭如何在MapReduce中將XML作為輸出傳送。

MapReduce不包含對XML的內建支援,因此我們轉向另一個Apache專案——Mahout,一個提供XML InputFormat的機器學習系統。 要了解XML InputFormat,你可以編寫一個MapReduce作業,該作業使用Mahout的XML輸入格式從Hadoop的配置檔案(HDFS)中讀取屬性名稱和值。

第一步是對作業進行配置:

 

Mahout的XML輸入格式很簡陋,我們需要指定檔案搜尋的確切開始和結束XML標記,並使用以下方法拆分檔案(並提取記錄):

  1. 檔案沿著HDFS塊邊界分成不連續的部分,用於資料本地化。

  2. 每個map任務都在特定的輸入拆分上執行,map任務尋求輸入拆分的開始,然後繼續處理檔案,直到第一個xmlinput.start。

  3. 重複發出xmlinput.start和xmlinput.end之間的內容,直到輸入拆分的末尾。

接下來,你需要編寫一個mapper來使用Mahout的XML輸入格式。Text表單已提供XML元素,因此需要使用XML解析器從XML中提取內容。

 

表3.1 使用Java的STAX解析器提取內容

該map具有一個Text例項,該例項包含start和end標記之間資料的String表示。在此程式碼中,我們可以使用Java的內建Streaming API for XML(StAX)解析器提取每個屬性的鍵和值並輸出。

如果針對Cloudera的core-site.xml執行MapReduce作業並使用HDFS cat命令顯示輸出,將看到以下內容:

 

此輸出顯示已成功使用XML作為MapReduce的輸入序列化格式。不僅如此,還可以支援巨大的XML檔案,因為輸入格式支援拆分XML。

寫XML

當可以正常讀XML之後,我們要解決的就是如何寫XML。 在reducer中,呼叫main reduce方法之前和之後都會發生回撥,可以使用它來發出開始和結束標記,如下所示。

 

 

表3.2 用於發出開始和結束標記的reducer

這也可以嵌入到OutputFormat中。

Pig

如果想在Pig中使用XML,Piggy Bank library(使用者貢獻的Pig程式碼庫)包含一個XMLLoader。其工作方式與此技術非常相似,可捕獲開始和結束標記之間的所有內容,並將其作為Pig元組中的單位元組陣列欄位提供。 

Hive

目前沒有辦法在Hive中使用XML,必須寫一個自定義SerDe。

總結

Mahout的XmlInputFormat可幫助使用XML,但它對開始和結束元素名稱的精確字串匹配很敏感。如果元素標記包含具有變數值的屬性,無法控制元素生成或者可能導致使用XML名稱空間限定符,則此方法不可用。

如果可以控制輸入中的XML,則可以透過在每行使用單個XML元素來簡化此練習。這允許使用內建的MapReduce基於文字的輸入格式(例如TextInputFormat),它將每一行視為記錄並拆分。

值得考慮的另一個選擇是預處理步驟,可以將原始XML轉換為每個XML元素的單獨行,或者將其轉換為完全不同的資料格式,例如SequenceFile或Avro,這兩種格式都解決了拆分問題。

現在,你已經瞭解如何使用XML,讓我們來處理另一種流行的序列化格式JSON。

3.2.2 JSON

JSON共享XML的機器和人類可讀特徵,並且自21世紀初以來就存在。它比XML簡潔,但是沒有XML中豐富的型別和驗證功能。

如果有一些程式碼正在從流式REST服務中下載JSON資料,並且每小時都會將檔案寫入HDFS。由於下載的資料量很大,因此生成的每個檔案大小為數千兆位元組。

如果你被要求編寫一個MapReduce作業,需要將大型JSON檔案作為輸入。你可以將問題分為兩部分:首先,MapReduce沒有與JSON一起使用的InputFormat; 其次,如何分割JSON?

圖3.7顯示了拆分JSON問題。 想象一下,MapReduce建立了一個拆分,如圖所示。對此輸入拆分進行操作的map任務將執行對輸入拆分的搜尋,以確定下一條記錄的開始。對於諸如JSON和XML之類的檔案格式,由於缺少同步標記或任何其他標識記錄開頭,因此知道下一條記錄何時開始是很有挑戰性的。

JSON比XML等格式更難分割成不同的段,因為JSON沒有token(如XML中的結束標記)來表示記錄的開頭或結尾。

問題

希望在MapReduce中使用JSON輸入,並確保可以為併發讀取分割槽輸入JSON檔案。

解決方案

Elephant Bird LzoJsonInputFormat被用來作為建立輸入格式類以使用JSON元素的基礎,該方法可以使用多行JSON。

 

圖3.7 使用JSON和多個輸入拆分的問題示例

討論

Elephant Bird()是一個開源專案,包含用於處理LZOP壓縮的有用程式,它有一個可讀取JSON的LzoJsonInputFormat,儘管要求輸入檔案是LZOP-compressed。,但可以將Elephant Bird程式碼用作自己的JSON InputFormat模板,該模板不具有LZOP compression要求。

此解決方案假定每個JSON記錄位於單獨的行上。JsonRecordFormat很簡單,除了構造和返回JsonRecordFormat之外什麼也沒做,所以我們將跳過該程式碼。JsonRecordFormat向mapper發出LongWritable,MapWritable  key/value,其中MapWritable是JSON元素名稱及其值的對映。

我們來看看RecordReader的工作原理,它使用LineRecordReader,這是一個內建的MapReduce讀取器。要將該行轉換為MapWritable,讀取器使用json-simple解析器將該行解析為JSON物件,然後迭代JSON物件中的鍵並將它們與其關聯值一起放到MapWritable。mapper在LongWritable中被賦予JSON資料,MapWritable pairs可以相應地處理資料。

 

以下顯示了JSON物件示例:

 

該技巧假設每行一個JSON物件,以下程式碼顯示了在此示例中使用的JSON檔案:

 

現在將JSON檔案複製到HDFS並執行MapReduce程式碼。MapReduce程式碼寫入每個JSON key/value對並輸出:

 

寫JSON

類似於3.2.1節,編寫XML的方法也可用於編寫JSON。

Pig

Elephant Bird包含一個JsonLoader和LzoJsonLoader,可以使用它來處理Pig中的JSON,這些載入器使用基於行的JSON。每個Pig元組都包含該行中每個JSON元素的chararray欄位。

Hive

Hive包含一個可以序列化JSON的DelimitedJSONSerDe類,但遺憾的是無法對其進行反序列化,因此無法使用此SerDe將資料載入到Hive中。

總結

此解決方案假定JSON輸入的結構為每個JSON物件一行。那麼,如何使用跨多行的JSON物件?GitHub上有一個專案( )可以在單個JSON檔案上進行多個輸入拆分,此方法可搜尋特定的JSON成員並檢索包含的物件。

你可以檢視名為hive-json-serde的Google專案,該專案可以同時支援序列化和反序列化。

正如你所看到的,在MapReduce中使用XML和JSON是非常糟糕的,並且對如何佈局資料有嚴格要求。MapReduce對這兩種格式的支援也很複雜且容易出錯,因為它們不適合拆分。顯然,需要檢視具有內部支援且可拆分的替代檔案格式。

下一步是研究更適合MapReduce的複雜檔案格式,例如Avro和SequenceFile。

3.3 大資料序列化格式

當使用scalar或tabular資料時,非結構化文字格式很有效。諸如XML和JSON之類的半結構化文字格式可以對包括複合欄位或分層資料的複雜資料結構進行建模。但是,當處理較大資料量時,我們更需要具有緊湊序列化表單的序列化格式,這些格式本身支援分割槽並具有模式演變功能。

在本節中,我們將比較最適合MapReduce大資料處理的序列化格式,並跟進如何將它們與MapReduce一起使用。

3.3.1 比較SequenceFile,Protocol Buffers,Thrift和Avro

根據經驗,在選擇資料序列化格式時,以下特徵非常重要:

  • 程式碼生成——某些序列化格式具有程式碼生成作用的庫,允許生成豐富的物件,使更容易與資料互動。生成的程式碼還提供了類似安全性等額外好處,以確保消費者和生產者使用正確的資料型別。

  • 架構演變 - 資料模型隨著時間的推移而發展,重要的是資料格式支援修改資料模型的需求。模式演變功能允許你新增、修改並在某些情況下刪除屬性,同時為讀和寫提供向後和向前相容性。

  • 語言支援 - 可能需要使用多種程式語言訪問資料,主流語言支援資料格式非常重要。

  • 資料壓縮 - 資料壓縮非常重要,因為可以使用大量資料。並且,理想的資料格式能夠在寫入和讀取時內部壓縮和解壓縮資料。如果資料格式不支援壓縮,那麼對於程式設計師而言,這是一個很大的問題,因為這意味著必須將壓縮和解壓縮作為資料管道的一部分進行管理(就像使用基於文字的檔案格式一樣)。

  • 可拆分性 - 較新的資料格式支援多個並行讀取器,可讀取和處理大型檔案的不同塊。檔案格式包含同步標記至關重要(可隨機搜尋和掃描到下一條記錄開頭)。

  • 支援MapReduce和Hadoop生態系統 - 選擇的資料格式必須支援MapReduce和其他Hadoop生態系統關鍵專案,例如Hive。如果沒有這種支援,你將負責編寫程式碼以使檔案格式適用於這些系統。

表3.1比較了流行的資料序列化框架,以瞭解它們如何相互疊加。以下討論提供了有關這些技術的其他背景知識。

 表3.1資料序列化框架的功能比較

讓我們更詳細地看一下這些格式。 

SequenceFile

建立SequenceFile格式是為了與MapReduce、Pig和Hive一起使用,因此可以很好地與所有工具整合。缺點主要是缺乏程式碼生成和版本控制支援,以及有限的語言支援。

Protocol Buffers

Protocol Buffers 已被Google大量用於互操作,其優勢在於其版本支援二進位制格式。缺點是MapReduce(或任何第三方軟體)缺乏對讀取Protocol Buffers 序列化生成的檔案支援。但是,Elephant Bird可以在容器檔案中使用Protocol Buffers序列化。

Thrift

Thrift是Facebook內部開發的資料序列化和RPC框架,在本地資料序列化格式中不支援MapReduce,但可以支援不同的wire-level資料表示,包括JSON和各種二進位制編碼。 Thrift還包括具有各種型別伺服器的RPC層。本章將忽略RPC功能,並專注於資料序列化。

Avro

Avro格式是Doug Cutting建立的,旨在幫助彌補SequenceFile的不足。

Parquet

Parquet是一種具有豐富Hadoop系統支援的柱狀檔案格式,可以與Avro、Protocol Buffers和Thrift等友好工作。儘管 Parquet 是一個面向列的檔案格式,不要期望每列一個資料檔案。Parquet 在同一個資料檔案中儲存一行中的所有資料,以確保在同一個節點上處理時一行的所有列都可用。Parquet 所做的是設定 HDFS 塊大小和最大資料檔案大小為 1GB,以確保 I/O 和網路傳輸請求適用於大批次資料。

基於上述評估標準,Avro似乎最適合作為Hadoop中的資料序列化框架。SequenceFile緊隨其後,因為它與Hadoop具有內在相容性(它設計用於Hadoop)。

你可以在Github上檢視jvm-serializers專案,該專案執行各種基準測試,以根據序列化和反序列化時間等比較檔案格式。它包含Avro,Protocol Buffers和Thrift基準測試以及許多其他框架。

在瞭解了各種資料序列化框架後,我們將在接下來幾節中專門討論這些格式。

相關文章:

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/

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

相關文章