瞭解hadoop,首先就需要先了解hadoop的數據流,就像瞭解servlet的生命週期似的。hadoop是一個分佈式存儲(hdfs)和分佈式計算框架(mapreduce),但是hadoop也有一個很重要的特性:hadoop會將mapreduce計算移動到存儲有部分數據的各臺機器上。
術語
MapReduce 作業(job)是客戶端需要執行的一個工作單元:它包括輸入數據、mapreduce程序和配置信息。hadoop將作業分成若干個小任務(task)來執行,其中包括兩類任務:map任務和reduce任務。
有兩類節點控制着作業執行過程:一個jobtracker及一系列tasktracker。jobtracker通過調度tasktracker上運行的任務,來協調所有運行在系統上的作業。tasktracker在運行任務的同時將運行進度報告發送給jobtracker,jobtracker由此記錄每項作業任務的整體進度情況。如果其中一個任務失敗,jobtracker可以在另外一個tasktracker節點上重新調度該任務。
有兩類節點控制着作業執行過程:一個jobtracker及一系列tasktracker。jobtracker通過調度tasktracker上運行的任務,來協調所有運行在系統上的作業。tasktracker在運行任務的同時將運行進度報告發送給jobtracker,jobtracker由此記錄每項作業任務的整體進度情況。如果其中一個任務失敗,jobtracker可以在另外一個tasktracker節點上重新調度該任務。
輸入
hadoop將mapreduce的輸入數據劃分成等長的小數據塊,稱爲輸入分片(input split)或簡稱分片。hadoop爲每個分片構建一個map任務,並由該任務來運行用戶自定義的map函數從而處理分片中的每條記錄。
對於大多數作業來說,一個合理的分片大小趨向於HDFS的一個塊的大小,默認是64M,不過可以針對集羣調整這個默認值。分片的大小一定要根據運行的任務來定,如果分片過小,那麼管理分片的總時間和構建map任務的總時間將決定着作業的整個執行時間。
hadoop在存儲有輸入數據的節點上運行map任務,可以獲得最佳性能,這就是所謂的數據本地化優化。因爲塊是hdfs存儲數據的最小單元,每個塊可以在多個節點上同時存在(備份),一個文件被分成的各個塊被隨機分部在多個節點上,因此如果一個map任務的輸入分片跨越多個數據塊,那麼基本上沒有一個節點能夠恰好同時存在這幾個連續的數據塊,那麼map任務就需要首先通過網絡將不存在於此節點上的數據塊遠程複製到本節點上再運行map函數,那麼這種任務顯然效率非常低。
輸出
map任務將其輸出寫入到本地磁盤,而非HDFS。這是因爲map的輸出是中間結果:該中間結果有reduce任務處理後才產生最終結果(保存在hdfs中)。而一旦作業完成,map的輸出結果可以被刪除。
reduce任務並不具備數據本地化優勢:單個reduce任務的輸入通常來自於所有的mapper任務的輸出。reduce任務的輸出通常存儲於HDFS中以實現可靠存儲。
數據流
作業根據設置的reduce任務的個數不同,數據流也不同,但大同小異。reduce任務的數量並非由輸入數據的大小決定的,而是可以通過手動配置指定的。
單個reduce任務
多個reduce任務
如果是多個reduce任務的話,則每個map任務都會對其輸出進行分區(partition),即爲每個reduce任務創建一個分區。分區有用戶定義的分區函數控制,默認的分區器(partitioner) 通過哈希函數來分區。
map任務和reduce任務之間的數據流稱爲shuffle(混洗)。
map任務和reduce任務之間的數據流稱爲shuffle(混洗)。
沒有reduce任務
當然也可能出現不需要執行reduce任務的情況,即數據可以完全的並行。
combiner(合併函數)
順便在這說下combiner吧,hadoop運行用戶針對map任務的輸出指定一個合併函數,合併函數的輸出作爲reduce函數的輸入。其實合併函數就是一個優化方案,說白了就是在map任務執行後在本機先執行合併函數(通常就是reduce函數的拷貝),減少網絡傳輸量。