大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?


對於很多用戶來說10G數據可能並不大,對這個數量級的數據分析能算得上是大數據嗎?

當然算了,我們只是拿這個10G的數據作為一個例子,系統能處理10G的數據,理論上就能處理100G甚至是1T數據。這要看咱們的硬件配置情況和所需要耗費的時間。假如1T數據1臺服務器需要5小時才能出結果,那我們用60臺服務器去並行計算,可能2分鐘結果就能出來了。

本文假設你已經查看過我的Hadoop大數據規劃以及安裝配置的文章,已經安裝並配置好PHP軟件,安裝並配置好Rsync軟件。

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

PHP還能進行大數據計算呢?

當然能了。

Hadoop本身是Java寫的,所以順理成章的,給Hadoop寫MapReduce,人們會自然地想到Java。但Hadoop裡面有個Contrib叫做Hadoop Streaming,這是一個小工具,為Hadoop提供Streaming支持。利用該Streaming提供的API,允許用戶使用任何語言編寫Map函數和Reduce函數。因此,PHP也可以藉助該API來進行大數據計算與分析。

另外這裡面牽涉到下面這個問題。

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

MapReduce是什麼?

概念"Map(映射)"和"Reduce(歸約)",是它的主要思想,它極大地方便了編程人員在不會分佈式並行編程的情況下,將自己的程序運行在分佈式系統上。

從網上一搜就能搜到非常多的關於MapReduce的內容,寫的都很好。但是不是很好理解。我根據我的理解直白的說明如下,歡迎拍磚:

1、一個超大數據文件(超過1T)切成6份(我們有6個DateNode),分別存到6臺服務器上;

2、我們的計算程序分別在這6臺服務器上計算自己的那份,得出結果,過程中可能會把自己的那份切成更小的份數(Hadoop默認一份為128M);

3、6臺服務器計算的結果再彙總到一個服務器上,進行彙總計算,得出最終結果。

以上例子"把數據分到6臺服務器並計算出結果"就是對Map(映射)最直白的其中一種解釋;而"6臺服務器計算結果彙總到一起,得出最終結果"就是對Reduce(歸約)最直白的其中一種解釋。

這麼一看,是不是就沒什麼神秘的了呢?

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

準備一個10G的數據文件

手頭不容易找到10G那麼大的文本文件,那咱就自己創造一個。隨便打開一個英文網站,比如Firewalld的官網blog頁面:

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

頁面內全選(Ctrl+A),複製(Ctrl+C),然後打開CentOS Linux 8的SSH客戶端。

新建一個文件名問10G.txt的文件,然後把剛才複製的內容粘貼進去,命令如下:

<code>vi 10G.txt/<code>
大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

然後就是不斷的去找英文的內容,粘貼進去,感覺差不多了,進行下一步。

因為我們不可能一直複製出10G的文字那麼多,那我們就利用CentOS Linux 8,自己複製自己,最終得出這麼多內容,命令如下:

<code>cat 10G.txt >> 11G.txt/<code>
<code>cat 11G.txt >> 10G.txt/<code>

不斷的重複這個過程,因為每次都翻倍,文件大小呈現指數級增長,很快我們就能得到一個10G的文件了。文件大小超過500M之後,會變的有點慢,有耐心的等一下。

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?


將10G.txt上傳至Hadoop的分佈式存儲系統HDFS,執行以下命令:

查看HDFS上的根目錄:

<code>hdfs dfs -ls //<code>

在HDFS的根目錄下簡歷input目錄:

<code>hdfs dfs -mkdir /input/<code>

查看input目錄是否創建成功:

<code>hdfs dfs -ls //<code>

將10G.txt上傳至HDFS的/input目錄下:

<code>hdfs dfs -put 10G.txt /input/<code>
大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

查看10G.txt上傳至/input目錄是否成功:

<code>hdfs dfs -ls /input/<code>
大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

根據咱們設定的規則,HDFS會保存3個副本。也就是說咱們雖然上傳了10G數據,但是HDFS會在整個系統上存儲30G的數據。從上圖最後一行的數據也能看的出來,第一個9.6G是咱們上傳的數據量,後面的28.9G是HDFS實際存儲的量。

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

WEB查看一下,每臺服務器上存儲了大約5G的數據,6臺DataNode正好大約是30G(見上圖)。

上傳這10G文件的時候服務器的壓力還是比較大的。CPU經常在75%徘徊,64G內存已經用去將近60G,磁盤的壓力也很大。從截圖中也能看到,上傳開始時間"22:52:54",上傳結束時間"22:59:12",花費了6分18秒的時間。這就是用一臺服務器來模擬8臺服務器的弱點。如果是真正的8臺服務器,哪怕就是普通的PC安裝的Linux系統搭建的服務器,只要裝上萬兆(10G)的網卡,再來個10塊硬盤組Raid0,時間估計能壓縮到1分鐘以內。因為Hadoop技術上允許一部分DataNode掉線後系統正常運行,所以可以組Raid0提供存儲服務來提高系統運行性能。

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

至此,這個10G的txt文件已經順利的上傳到了Hadoop的分佈式存儲服務HDFS上。

如果你還有多個文件要一起分析,都傳到這個/input目錄下即可。也就是說後面的分析程序是支持多個文件合併進行數據分析的,你不用自己手動把這幾個文件合併到一個文件裡面。

準備PHP數據分析程序

在集群的每臺機器上安裝PHP,並保持目錄結構和配置文件一致,參考我的在CentOS Linux 8 上安裝PHP的文章。並且已經安裝並配置好了Rsync。

本文假定你已經做好了上述安裝,如果沒有做好,可以查看相關參考資料。

根據咱們的集群規劃,主Rsync位於Hadoop222服務器,所以以下的程序編寫部分我們在Hadoop222(192.168.1.222)上面操作。

編寫Mapper程序

用root執行以下命令,配置好Hadoop用的PHP目錄

<code>mkdir -p /wwwroot/hadoop/<code>
<code>chown -R hadoop:hadoop /wwwroot/hadoop/<code>

轉為Hadoop用戶執行以下操作:

<code>su hadoop/<code>
<code>vi /wwwroot/hadoop/mapper.php/<code>

輸入以下內容:

#!/usr/bin/php

ini_set('memory_limit', '-1'); //內存使用不做限制,限制內存的事情交給系統自己解決

$word2count = array();

//STDIN (標準輸入) = fopen("php://stdin", "r");

//一行一行的讀入數據

while (($line = fgets(STDIN)) !== false)

{

//刪除前後的空格,字符轉為小寫

$line = strtolower(trim($line));

//"\\W匹配:任意個非單詞字符"

//通過"非單詞字符"分割句子為"單詞字符"

// PREG_SPLIT_NO_EMPTY返回分隔後的非空部分

$words = preg_split('/\\W/', $line, 0, PREG_SPLIT_NO_EMPTY);

//單詞計數增加

foreach ($words as $word)

{

if(!isset($word2count[$word]))

{

$word2count[$word] = 0;

}

$word2count[$word] += 1;

}

}

//輸出結果到STDOUT(標準輸出)

//我們這裡的輸出就是Reduce的輸入

//即:reducer .php的輸入

foreach ($word2count as $word => $count)

{

// PHP_EOL:換行符號,unix系列輸出\\n,windows系列輸出\\r\\n,mac用輸出\\r

// chr(9):製表符分隔tab-delimited

echo $word, chr(9), $count, PHP_EOL;

}

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

這段代碼的大致意思是:把輸入的每行文本中的單詞找出來,並以:

zoo 1

hello 3

world 5

這樣的形式輸出出來。

編寫Reducer程序

用Hadoop用戶執行以下操作:

<code>su hadoop/<code>
<code>vi /wwwroot/hadoop/reducer.php/<code>

輸入以下內容:

#!/usr/bin/php

ini_set('memory_limit', '-1'); //內存使用不做限制,限制內存的事情交給系統自己解決

$word2count = array();

//STDIN (標準輸入) = fopen("php://stdin", "r");

//一行一行的讀入數據

while (($line = fgets(STDIN)) !== false) {

//刪除兩頭的空格

$line = trim($line);

//分析我們從mapper.php獲得的輸入

list($word, $count) = explode(chr(9), $line);

//將count(當前為字符串)轉換為int

$count = intval($count);

//計算單詞的數量總和

if ($count > 0) $word2count[$word] += $count;

}

//按詞彙分類sort the words lexigraphically

//這個集合不是必需的,我們這樣做只是為了

//使我們的最終輸出看起來更像官方的Hadoop單詞計數示例

// ksort() 函數對關聯數組按照鍵名進行升序排序。

ksort($word2count);

//輸出結果到STDOUT(標準輸出)

foreach ($word2count as $word => $count)

{

echo $word, chr(9), $count, PHP_EOL;

}


大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

這段代碼的大意是彙總各Mapper的統計結果,最終得出每個單詞出現了多少次數,排序後以:

hello 2

world 1

zoo 5

這樣的形式輸出,接受的輸入方式"hello 1",也就是mapper.php輸出的方式。

給Mapper和Reducer賦予可執行權限。

<code>chmod +x /wwwroot/hadoop/mapper.php /wwwroot/hadoop/reducer.php/<code> 

執行PHP的MapReduce進行大數據分析

上面已經完成數據上傳,代碼的編寫。我們要在每臺服務器上查看一下,是否已經將PHP代碼同步到每一臺服務器上了。

在每臺服務器上都執行以下命令:

<code>ll /wwwroot/hadoop//<code>
大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

必須保證每臺服務器上都有上述的兩個PHP文件,才能執行以下大數據計算的命令:

<code>hadoop jar /home/hadoop/hadoop/share/hadoop/tools/lib/hadoop-streaming-3.2.1.jar -mapper /wwwroot/hadoop/mapper.php -reducer /wwwroot/hadoop/reducer.php -input /input/* -output /output/<code>
大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

由於數據量比較大,所以數據計算的執行時間會比較長,需要耐心等待。

從服務器上的截圖可以看到,服務器已經拿出100%的CPU資源,幾乎100%的內存資源,每塊硬盤輪流100%的資源,來完成咱們的大數據計算任務。

大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

系統計算完畢之後,查看一下輸出的結果,咱們設定的輸出目錄是HDFS的/output:

<code>hdfs dfs -du -h /output/<code>

把輸出結果下載下來查看:

<code>hdfs dfs -get /output/part-00000/<code>

當然也可以在線查看,不過感覺不太方便,執行下述命令:

<code>hdfs dfs -cat /output/part-00000/<code>

或者這個命令:

<code>hdfs dfs -tail -f /output/part-00000/<code>


大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?

從上面的截圖中可以看到,為了分析這10G的數據,程序執行的開始時間是"23:26:23",程序執行的結束時間是"23:37:28",共花費了11分5秒。

上述得到的結果是:字符串"0"在文件中出現了"36366795"次,字符串"00"在文件中出現了"105411"次,依次類推,整個計算結果的文件part-00000大小是30.9K。


大數據實戰:10G數據文件Hadoop和PHP多久能分析出結果?


總結

通過以上測試可以發現,用PHP做大數據分析真的非常容易。由於Hadoop提供了MapReduce接口,我們在編寫PHP程序的時候,只需要關注邏輯處理即可,分片計算的部分Hadoop幫我們搞定了。

我們使用了一臺服務器虛擬成8臺服務器,對10G的數據進行分析,花費了11分5秒的時間。這個時間長度在可接受的範圍之內,但如果做成多臺真實的服務器進行計算,時間肯定會大幅縮減。如果有條件的時候,還真想試試。


分享到:


相關文章: