天天看點

《Hive程式設計指南》一1.1 Hadoop和MapReduce綜述

本節書摘來異步社群《hive程式設計指南》一書中的第1章,第1.1節,作者: 【美】edward capriolo , dean wampler , jason rutherglen 譯者: 曹坤,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。

如果使用者已經熟悉hadoop和mapreduce計算模型的話,那麼可以跳過本節。雖然使用者無需精通mapreduce就可以使用hive,但是了解mapreduce的基本原理将幫有助于使用者了解hive在底層是如何運作的,以及了解如何才能更高效地使用hive。

我們在這裡提供了一個關于hadoop和mapreduce的簡要描述。更多細節,請參考tom white (o’reilly)所著的《hadoop權威指南》一書。

mapreduce

mapreduce是一種計算模型,該模型可将大型資料處理任務分解成很多單個的、可以在伺服器叢集中并行執行的任務。這些任務的計算結果可以合并在一起來計算最終的結果。

mapreduce程式設計模型是由谷歌(google)開發的。google通過一篇很有影響力的論文對這個計算模型進行了描述,本書附錄部分可檢視到該論文,名為《mapreduce:大資料之上的簡化資料處理》。一年後,另一篇名為《google檔案系統》的論文介紹了google檔案系統。這兩篇論文啟發了道·卡丁(doug cutting)開發了hadoop。

mapreduce這個術語來自于兩個基本的資料轉換操作:map過程和reduce過程。一個map操作會将集合中的元素從一種形式轉換成另一種形式。在這種情況下,輸入的鍵-值對會被轉換成零到多個鍵-值對輸出。其中,輸入和輸出的鍵必須完全不同,而輸入和輸出的值則可能完全不同。

在mapreduce計算架構中,某個鍵的所有鍵-值對都會被分發到同一個reduce操作中。确切地說,這個鍵和這個鍵所對應的所有值都會被傳遞給同一個reducer。reduce過程的目的是将值的集合轉換成一個值(例如對一組數值求和或求平均值),或者轉換成另一個集合。這個reducer最終會産生一個鍵-值對。再次說明一下,輸入和輸出的鍵和值可能是不同的。需要說明的是,如果job不需要reduce過程的話,那麼也是可以無reduce過程的。

hadoop提供了一套基礎設施來處理大多數困難的工作以保證任務能夠執行成功。例如,hadoop決定如果将送出的job分解成多個獨立的map和reduce任務(task)來執行,它就會對這些task進行排程并為其配置設定合适的資源,決定将某個task配置設定到叢集中哪個位置(如果可能,通常是這個task所要處理的資料所在的位置,這樣可以最小化網絡開銷)。它會監控每一個task以確定其成功完成,并重新開機一些失敗的task。

hadoop分布式檔案系統(也就是hdfs),或者一個同類的分布式檔案系統,管理着叢集中的資料。每個資料塊(block)都會被備援多份(通常預設會備援3份),這樣可以保證不會因單個硬碟或伺服器的損壞導緻資料丢失。同時,因為其目标是優化處理非常大的資料集,是以hdfs以及類似的檔案系統所使用的資料塊都非常大,通常是64mb或是這個值的若幹倍。這麼大的資料塊可以在硬碟上連續進行存儲,這樣可以保證以最少的磁盤尋址次數來進行寫入和讀取,進而最大化提高讀寫性能。

為了更清晰地介紹mapreduce,讓我們來看一個簡單的例子。word count算法已經被稱為是mapreduce計算架構中的“hello world”程式[7]了。word count會傳回在語料庫(單個或多個檔案)中出現的所有單詞以及單詞出現的次數。輸出内容會顯示每個單詞和它的頻數,每行顯示一條。按照通常的習慣,單詞(輸出的鍵)和頻數(輸出的值)通常使用制表符進行分割。

圖1-1 顯示了在mapreduce計算架構中word count程式是如何運作的。

《Hive程式設計指南》一1.1 Hadoop和MapReduce綜述

這裡有很多内容要講,是以我們會從左到右來講解這個圖。

圖1-1中左邊的每個input(輸入)框内都表示一個單獨的檔案。例子中有4個檔案,其中第3個檔案是個空檔案,為了便于簡單描述,其他3個檔案都僅僅包含有少量幾個單詞。

預設情況下,每個文檔都會觸發一個mapper程序進行處理。而在實際場景下,大檔案可能會被劃分成多個部分,而每個部分都會被發送給一個mapper進行處理。同時,也有将多個小檔案合并成一個部分供某個mapper進行處理的方法。不過,我們目前不必深究這些細節性問題。

mapreduce計算架構中的輸入和輸出的基本資料結構是鍵-值對。當mapper程序啟動後,其将會被頻繁調用來處理檔案中的每行文本。每次調用中,傳遞給mapper的鍵是文檔中這行的起始位置的字元偏移量。對應的值是這行對應的文本。

在wordcount程式中,沒有使用字元偏移量(也就是沒有使用鍵)。值(也就是這行文本)可以使用很多種方式進行分割(例如,按照空格分隔是最簡單的方式,但是這樣會遺留下不需要的标點符号),最終這行文本會被分解成多個單詞。我們同時假定mapper會将每個單詞轉換成小寫,是以對于“fun”和“fun”會被認為是同一個單詞。

最後,對于這行文本中的每個單詞,mapper都會輸出一個鍵-值對,以單詞作為鍵并以數字1作為值(這裡1表示“出現1次”)。需要注意的是鍵和值的輸出資料類型和輸入資料類型是不同的。

hadoop神奇的地方一部分在于後面要進行的sort(排序)和shuffle(重新分發)過程。hadoop會按照鍵來對鍵-值對進行排序,然後“重新洗牌”,将所有具有相同鍵的鍵-值對分發到同一個reducer中。這裡有多種方式可以用于決定哪個reducer擷取哪個範圍内的鍵對應的資料。這裡我們先不必考慮這些問題。但是出于說明性目的,我們假設圖中使用了一個特殊的按字母數字劃分的過程(在實際執行中,會有所不同)。

對于mapper而言如果隻是簡單地對每個單詞輸出計數1這樣的處理的話,那麼會在sort和shuffle過程中産生一定的網絡和磁盤i/o浪費(不過,這樣并不會減少mapper的記憶體使用)。有一個優化就是跟蹤每個單詞的頻數,然後在mapper結束後隻輸出每個單詞在這個mapper中的總頻數。對于這個優化有好幾種實作方式,但是,最簡單的方式應該是邏輯是正确的,而且對于這個讨論,理由是充足的。

每個reducer的輸入同樣是鍵-值對,但是這次,每個鍵将是mapper所發現的單詞中的某一個單詞,而這個鍵對應的值将是所有mapper對于這個單詞計算出的頻數的一個集合。需要注意的是鍵的資料類型和值的集合中元素的資料類型和mapper的輸出是一緻的。也就是說,鍵的類型是一個字元串,而集合中的元素的資料類型是整型。

為了完成這個算法,所有的reducer需要做的事情就是将值集合中的頻數進行求和然後寫入每個單詞和這個單詞最終的頻數組成的鍵-值對。

word count不是一個虛構的例子。這個程式所産生的資料可用于拼寫檢查程式、計算機語言檢測和翻譯系統,以及其他應用程式。