Hadoop流
雖然Hadoop是用java寫的,但是Hadoop提供了Hadoop流,Hadoop流提供一個API, 允許用戶使用任何語言編寫map函數和reduce函數.
Hadoop流動關鍵是,它使用UNIX標準流作為程序與Hadoop之間的接口。因此,任何程序只要可以從標準輸入流中讀取數據,并且可以把數據寫入標準輸出流中,那么就可以通過Hadoop流使用任何語言編寫MapReduce程序的map函數和reduce函數。
例如:bin/hadoop jar contrib/streaming/hadoop-streaming-0.20.203.0.jar -mapper /usr/local/hadoop/mapper.php -reducer /usr/local/hadoop/reducer.php -input test/* -output out4
Hadoop流引入的包:hadoop-streaming-0.20.203.0.jar,Hadoop根目錄下是沒有hadoop-streaming.jar的,因為streaming是一個contrib,所以要去contrib下面找,以hadoop-0.20.2為例,它在這里:
-input:指明輸入hdfs文件的路徑
-output:指明輸出hdfs文件的路徑
-mapper:指明map函數
-reducer:指明reduce函數
mapper函數
mapper.php文件,寫入如下代碼:
#!/usr/local/php/bin/php <?php $word2count = array(); // input comes from STDIN (standard input) // You can this code :$stdin = fopen(“php://stdin”, “r”); while (($line = fgets(STDIN)) !== false) { // remove leading and trailing whitespace and lowercase $line = strtolower(trim($line)); // split the line into words while removing any empty string $words = preg_split('/\W/', $line, 0, PREG_SPLIT_NO_EMPTY); // increase counters foreach ($words as $word) { $word2count[$word] += 1; } } // write the results to STDOUT (standard output) // what we output here will be the input for the // Reduce step, i.e. the input for reducer.py foreach ($word2count as $word => $count) { // tab-delimited echo $word, chr(9), $count, PHP_EOL; } ?>
這段代碼的大致意思是:把輸入的每行文本中的單詞找出來,并以”
hello 1
world 1″
這樣的形式輸出出來。
和之前寫的PHP基本沒有什么不同,對吧,可能稍微讓你感到陌生有兩個地方:
PHP作為可執行程序
第一行的
#!/usr/local/php/bin/php告訴linux,要用#!/usr/local/php/bin/php這個程序作為以下代碼的解釋器。寫過linux shell的人應該很熟悉這種寫法了,每個shell腳本的第一行都是這樣: #!/bin/bash, #!/usr/bin/python
有了這一行,保存好這個文件以后,就可以像這樣直接把mapper.php當作cat, grep一樣的命令執行了:./mapper.php
使用stdin接收輸入
PHP支持多種參數傳入的方法,大家最熟悉的應該是從$_GET, $_POST超全局變量里面取通過Web傳遞的參數,次之是從$_SERVER['argv']里取通過命令行傳入的參數,這里,采用的是標準輸入stdin
它的使用效果是:
在linux控制臺輸入 ./mapper.php
mapper.php運行,控制臺進入等候用戶鍵盤輸入狀態
用戶通過鍵盤輸入文本
用戶按下Ctrl + D終止輸入,mapper.php開始執行真正的業務邏輯,并將執行結果輸出
那么stdout在哪呢?print本身已經就是stdout啦,跟我們以前寫web程序和CLI腳本沒有任何不同。
reducer函數
創建reducer.php文件,寫入如下代碼:
#!/usr/local/php/bin/php <?php $word2count = array(); // input comes from STDIN while (($line = fgets(STDIN)) !== false) { // remove leading and trailing whitespace $line = trim($line); // parse the input we got from mapper.php list($word, $count) = explode(chr(9), $line); // convert count (currently a string) to int $count = intval($count); // sum counts if ($count > 0) $word2count[$word] += $count; } // sort the words lexigraphically // // this set is NOT required, we just do it so that our // final output will look more like the official Hadoop // word count examples ksort($word2count); // write the results to STDOUT (standard output) foreach ($word2count as $word => $count) { echo $word, chr(9), $count, PHP_EOL; } ?>
這段代碼的大意是統計每個單詞出現了多少次數,并以”
hello 2
world 1″
這樣的形式輸出
用Hadoop來運行
把文件放入 Hadoop 的 DFS 中:
bin/hadoop dfs -put test.log test執行 php 程序處理這些文本(以Streaming方式執行PHP mapreduce程序:):
bin/hadoop jar contrib/streaming/hadoop-streaming-0.20.203.0.jar -mapper /usr/local/hadoop/mapper.php -reducer /usr/local/hadoop/reducer.php -input test/* -output out
注意:
1) input和output目錄是在hdfs上的路徑
2) mapper和reducer是在本地機器的路徑,一定要寫絕對路徑,不要寫相對路徑,以免到時候hadoop報錯說找不到mapreduce程序
3 ) mapper.php 和 reducer.php 必須復制到所有 DataNode 服務器上的相同路徑下, 所有的服務器都已經安裝php.且安裝路徑一樣.
查看結果
bin/hadoop d fs -cat /tmp/out/part-00000
轉自:http://blog.csdn.net/hguisu/article/details/7263746
原創文章,作者:s19930811,如若轉載,請注明出處:http://www.www58058.com/3084