咱們的CentOS Linux 8採用的是最小化安裝的方式,在這種方式下,系統默認是沒有安裝Python的。另外,由於咱們只是在系統上部署了Hadoop、Zookeeper等軟件,另外也部署了PHP,並沒有在系統上部署Python,所以咱們需要給它裝一個。
安裝Python
先看看都有那些Python的rpm包,運行以下命令:
dnf search python
執行安裝Python,系統會提示沒找到,也會提示系統中存在python2和python36:
dnf -y install python
我們安裝一下python36,執行以下命令:
dnf -y install python36
運行一下python,什麼?系統居然還是沒有python命令。這兩天剛看到一個CentOS Linux 8的命令alternatives,這個是用來控制一個系統裡面多個軟件版本的情況用的。我們設置python3作為我們的默認python命令,指定下列命令:
alternatives --config python
這樣就安裝Python3並設定它作為我們默認使用的Python程序成功。
寫一個測試的Python程序運行一下試試,具體如下:
vi hello.py
將以下內容粘貼進去:
我們的第一個Python程序執行成功了。
下面咱們編寫Python的MapReduce程序,網上找了一個示例,修改了一下,具體內容如下。
準備Python數據分析程序
因為咱們的服務器已經開始運行了,所以沒有辦法在一臺VMWare虛擬服務器上安裝好Python然後複製幾份過去了。這樣咱們就在另外7臺服務器上,分別執行上述的安裝命令。最後保證每臺服務器上的Python都能順利的執行那個測試程序即可。
根據咱們的集群規劃,主Rsync位於Hadoop222服務器,所以以下的程序編寫部分我們在Hadoop222(192.168.1.222)上面操作。
編寫Mapper程序
用Hadoop用戶執行以下命令:
su hadoop
mkdir -p /wwwroot/hadoop/python
cd /wwwroot/hadoop/python
我們先準備一個簡單的數據文件:
vi data.txt
把下列內容粘貼進去:
Hello world , Hello python !
Python is a programming language that lets you work more quickly and integrate your systems more effectively.
保存退出後,開始編寫mapper.py程序:
vi mapper.py
把下列內容粘貼進去:
#!/usr/bin/python
#導入sys和re庫
import sys
import re
#初始化全局字典dict
word_count = {}
#一行一行的接收輸入的文字並處理
for line in sys.stdin:
#將輸入的字符串去掉兩頭的空格,轉換成小寫字符
#並用"非字母數字及下劃線"分隔成列表
word_list = re.split('\\W', line.strip().lower())
#遍歷列表的每個單詞
for word in word_list:
#不統計空字符
if word.strip()=='' :
continue
#將獲取到的單詞標記1次
if word not in word_count.keys():
word_count[word] = 1
else:
#將獲取到的單詞標記增加1次
word_count[word] += 1
#將獲取到的字典排序(按照key排序,正序)
d = sorted(word_count.items(), key=lambda item:item[0], reverse=False)
#遍歷輸出
for k,v in d:
print(str(k) + '\\t' + str(v))
#mapper.py內容結束
給mapper.py賦予可執行權限:
chmod +x /wwwroot/hadoop/python/mapper.py
注意:代碼格式不能錯,特別是段落前的空格,因為空格也是Python必備的格式。
以上代碼會將輸入的字符串解析,並輸出如下形式內容(單詞正序排序):
hello 1
world 5
zoo 2
解釋:"world 5"的意思是world在文章中出現了5次
我們輸入以下命令測試程序執行的效果:
cat data.txt | /wwwroot/hadoop/python/mapper.py
輸出的內容與預期的結果一致。
編寫Reducer程序
用Hadoop用戶執行以下命令:
su hadoop
cd /wwwroot/hadoop/python
vi reducer.py
把下列內容粘貼進去:
#!/usr/bin/python
#導入sys和re庫
import sys
#初始化全局字典dict
word_count = {}
#一行一行的接收輸入的文字並處理
for line in sys.stdin:
#將輸入的字符串用製表符(TAB)分隔成列表
ss = line.strip().split('\\t')
#格式不對的不要(必須滿足類似"hello 1"格式)
if len(ss) < 2:
continue
k = ss[0].strip()
v = int(ss[1].strip())
#將獲取到的單詞標記v次
if k not in word_count.keys():
word_count[k] = v
else:
#將獲取到的單詞標記增加v次
word_count[k] += v
#將獲取到的字典排序(按照value排序,倒序)
d = sorted(word_count.items(), key=lambda item:item[1], reverse=True)
#遍歷輸出
for k,v in d:
print(str(k) + '\\t' + str(v))
#reducer.py內容結束
給Reducer賦予可執行權限。
chmod +x /wwwroot/hadoop/python/reducer.py
注意:代碼格式不能錯,特別是段落前的空格,因為空格也是Python必備的格式。
這段代碼的大意是彙總各Mapper的統計結果,最終得出每個單詞出現了多少次數,按照出現次數倒序排序後以:
world 5
zoo 2
hello 1
這樣的形式輸出,接受的輸入方式"hello 1",也就是mapper.php輸出的方式。
我們輸入以下命令測試程序執行的效果:
cat data.txt | /wwwroot/hadoop/python/mapper.py| /wwwroot/hadoop/python/reducer.py
輸出符合預期,這樣咱們就能放在Hadoop上運行了。
執行10G數據計算
1、所有的服務器上都安裝好Python;
2、保證mapper.py和reducer.py同步到各服務器上了;
3、為了對比PHP的計算效率,數據文件咱們還是使用PHP用的那個10G的文件。
我們在每臺服務器上都執行以下上邊的python程序,都能出結果,說明程序同步完畢,可以進行下一步了。
為了防止計算的結果會覆蓋掉上次的,所以Hadoop不允許把計算的結果存在與上次相同的目錄裡面。咱們先把output刪掉。當然,使用另外的目錄也可以,這裡就是演示一下怎麼在HDFS裡面刪除目錄。
執行命令:
hdfs dfs -rm -r /output
這樣,咱們就可以正式開始Python計算10G文本文件的程序了,參考一下PHP的,Python執行代碼如下:
hadoop jar /home/hadoop/hadoop/share/hadoop/tools/lib/hadoop-streaming-3.2.1.jar -mapper /wwwroot/hadoop/python/mapper.py -reducer /wwwroot/hadoop/python/reducer.py -input /input/* -output /output
我們可以看看系統資源佔用情況,CPU不用說了一直持續100%的狀態,內存佔用一直在57.4左右徘徊,硬盤依然是輪流100%的佔用。
程序執行完畢以後,下載執行的結果文件查看,結果符合預期。
最後再看看執行時間上與PHP的對比,下圖上面是Python的數據,下圖是PHP的數據。
總結
從最終的結果上看,可以得出結論如下:
1、程序的執行效率PHP更勝一籌,比Python少用了將近50%;
2、內存佔用上Python比PHP少使用了將近6G的內存,資源佔用少了10%
因為兩個都是腳本語言,學習難度和開發難度都類似。但在進行大數據計算的時候,從結論上看還是各有優勢的。