鍍金池/ 教程/ Python/ 使用 python 構建基于 hadoop 的 mapreduce 日志分析平臺
通過 memcached 實現(xiàn)領號排隊功能及 python 隊列實例
利用 pypy 提高 python 腳本的執(zhí)行速度及測試性能
Python FAQ3-python 中 的原始(raw)字符串
Mongodb 千萬級數據在 python 下的綜合壓力測試及應用探討
Parallel Python 實現(xiàn)程序的并行多 cpu 多核利用【pp 模塊】
python simplejson 模塊淺談
服務端 socket 開發(fā)之多線程和 gevent 框架并發(fā)測試[python 語言]
python Howto 之 logging 模塊
python 之 MySQLdb 庫的使用
關于 python 調用 zabbix api 接口的自動化實例 [結合 saltstack]
python 之利用 PIL 庫實現(xiàn)頁面的圖片驗證碼及縮略圖
Python 通過 amqp 消息隊列協(xié)議中的 Qpid 實現(xiàn)數據通信
python 中用 string.maketrans 和 translate 巧妙替換字符串
python linecache 模塊讀取文件用法詳解
Python 批量更新 nginx 配置文件
python 計算文件的行數和讀取某一行內容的實現(xiàn)方法
python+Django 實現(xiàn) Nagios 自動化添加監(jiān)控項目
多套方案來提高 python web 框架的并發(fā)處理能力
python 寫報警程序中的聲音實現(xiàn) winsound
python 調用 zabbix 的 api 接口添加主機、查詢組、主機、模板
對 Python-memcache 分布式散列和調用的實現(xiàn)
使用 python 構建基于 hadoop 的 mapreduce 日志分析平臺
一個腳本講述 python 語言的基礎規(guī)范,適合初學者
Python 編寫的 socket 服務器和客戶端
如何將 Mac OS X10.9 下的 Python2.7 升級到最新的 Python3.3
python 監(jiān)控文件或目錄變化
報警監(jiān)控平臺擴展功能 url 回調的設計及應用 [python 語言]
Python 處理 cassandra 升級后的回滾腳本
python 實現(xiàn) select 和 epoll 模型 socket 網絡編程
關于 B+tree (附 python 模擬代碼)
通過 python 和 websocket 構建實時通信系統(tǒng)[擴展 saltstack 監(jiān)控]

使用 python 構建基于 hadoop 的 mapreduce 日志分析平臺

http://wiki.jikexueyuan.com/project/python-actual-combat/images/48.jpg" alt="pic" />

流量比較大的日志要是直接寫入 Hadoop 對 Namenode 負載過大,所以入庫前合并,可以把各個節(jié)點的日志湊并成一個文件寫入 HDFS。 根據情況定期合成,寫入到 hdfs 里面。

咱們看看日志的大小,200 G 的 dns 日志文件,我壓縮到了 18 G,要是用 awk perl 當然也可以,但是處理速度肯定沒有分布式那樣的給力。

http://wiki.jikexueyuan.com/project/python-actual-combat/images/49.jpg" alt="pic" />

Hadoop Streaming 原理

mapper 和 reducer 會從標準輸入中讀取用戶數據,一行一行處理后發(fā)送給標準輸出。Streaming 工具會創(chuàng)建 MapReduce 作業(yè),發(fā)送給各個 tasktracker,同時監(jiān)控整個作業(yè)的執(zhí)行過程。

任何語言,只要是方便接收標準輸入輸出就可以做 mapreduce~

再搞之前我們先簡單測試下 shell 模擬 mapreduce 的性能速度~

http://wiki.jikexueyuan.com/project/python-actual-combat/images/50.jpg" alt="pic" />

看下他的結果,350 M 的文件用時 35 秒左右。

http://wiki.jikexueyuan.com/project/python-actual-combat/images/51.jpg" alt="pic" />

這是 2 G 的日志文件,居然用了 3 分鐘。 當然和我寫的腳本也有問題,我們是模擬 mapreduce 的方式,而不是調用 shell 下牛逼的 awk,gawk 處理。

http://wiki.jikexueyuan.com/project/python-actual-combat/images/52.jpg" alt="pic" />

awk 的速度!果然很霸道,處理日志的時候,我也很喜歡用 awk,只是學習的難度有點大,不像別的 shell 組件那么靈活簡單。

http://wiki.jikexueyuan.com/project/python-actual-combat/images/1.jpg" alt="pic" />

這是官方的提供的兩個 demo ~

map.py

#!/usr/bin/env python
"""A more advanced Mapper, using Python iterators and generators."""
import sys
def read_input(file):
    for line in file:
        # split the line into words
        yield line.split()
def main(separator='\t'):
    # input comes from STDIN (standard input)
    data = read_input(sys.stdin)
    for words in data:
        # 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
        #
        # tab-delimited; the trivial word count is 1
        for word in words:
            print '%s%s%d' % (word, separator, 1)
if __name__ == "__main__":
    main()

reduce.py 的修改方式

#!/usr/bin/env python
"""A more advanced Reducer, using Python iterators and generators."""
from itertools import groupby
from operator import itemgetter
import sys
def read_mapper_output(file, separator='\t'):
    for line in file:
        yield line.rstrip().split(separator, 1)
def main(separator='\t'):
    # input comes from STDIN (standard input)
    data = read_mapper_output(sys.stdin, separator=separator)
    # groupby groups multiple word-count pairs by word,
    # and creates an iterator that returns consecutive keys and their group:
    #   current_word - string containing a word (the key)
    #   group - iterator yielding all ["<current_word>", "<count>"] items
    for current_word, group in groupby(data, itemgetter(0)):
        try:
            total_count = sum(int(count) for current_word, count in group)
            print "%s%s%d" % (current_word, separator, total_count)
        except ValueError:
            # count was not a number, so silently discard this item
            pass
if __name__ == "__main__":
    main()

咱們再簡單點:

#!/usr/bin/env python
import sys
for line in sys.stdin:
    line = line.strip()
    words = line.split()
    for word in words:
        print '%s\t%s' % (word, 1)
#!/usr/bin/env python

from operator import itemgetter
import sys

current_word = None
current_count = 0
word = None

for line in sys.stdin:
    line = line.strip()
    word, count = line.split('\t', 1)
    try:
        count = int(count)
    except ValueError:
        continue
    if current_word == word:
        current_count += count
    else:
        if current_word:
            print '%s\t%s' % (current_word, current_count)
        current_count = count
        current_word = word

if current_word == word:
    print '%s\t%s' % (current_word, current_count)

咱們就簡單模擬下數據,跑個測試

http://wiki.jikexueyuan.com/project/python-actual-combat/images/54.jpg" alt="pic" />

剩下就沒啥了,在 hadoop 集群環(huán)境下,運行 hadoop 的 steaming.jar 組件,加入 mapreduce 的腳本,指定輸出就行了. 下面的例子我用的是 shell 的成分。

[root@101 cron]#$HADOOP_HOME/bin/hadoop  jar $HADOOP_HOME/contrib/streaming/hadoop-*-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper cat \
-reducer wc

詳細的參數,對于咱們來說提供性能可以把 tasks 的任務數增加下,根據情況自己測試下,也別太高了,增加負擔。

(1)-input:輸入文件路徑
(2)-output:輸出文件路徑
(3)-mapper:用戶自己寫的 mapper 程序,可以是可執(zhí)行文件或者腳本
(4)-reducer:用戶自己寫的 reducer 程序,可以是可執(zhí)行文件或者腳本
(5)-file:打包文件到提交的作業(yè)中,可以是 mapper 或者 reducer 要用的輸入文件,如配置文件,字典等。
(6)-partitioner:用戶自定義的 partitioner 程序
(7)-combiner:用戶自定義的 combiner 程序(必須用 java 實現(xiàn))
(8)-D:作業(yè)的一些屬性(以前用的是-jonconf),具體有:

1)mapred.map.tasks:map task 數目
2)mapred.reduce.tasks:reduce task 數目
3)stream.map.input.field.separator/stream.map.output.field.separator: map task 輸入/輸出數 據的分隔符,默認均為 \t。
4)stream.num.map.output.key.fields:指定 map task 輸出記錄中 key 所占的域數目
5)stream.reduce.input.field.separator/stream.reduce.output.field.separator:reduce task 輸入/輸出數據的分隔符,默認均為 \t。
6)stream.num.reduce.output.key.fields:指定 reduce task 輸出記錄中 key 所占的域數目

這里是統(tǒng)計 dns 的日志文件有多少行 ~

http://wiki.jikexueyuan.com/project/python-actual-combat/images/55.jpg" alt="pic" />

在 mapreduce 作為參數的時候,不能用太多太復雜的 shell 語言,他不懂的~

可以寫成 shell 文件的模式;

#! /bin/bash
while read LINE; do
#  for word in $LINE
#  do
#    echo "$word 1"
        awk '{print $5}'                                                                                                       
  done
done
#! /bin/bash
count=0
started=0
word=""
while read LINE;do
  goodk=`echo $LINE | cut -d ' '  -f 1`
  if [ "x" == x"$goodk" ];then
     continue
  fi
  if [ "$word" != "$goodk" ];then
    [ $started -ne 0 ] && echo -e "$word\t$count"
    word=$goodk                                                                                                                
    count=1
    started=1
  else
    count=$(( $count + 1 ))
  fi
done

有時候會出現(xiàn)這樣的問題,好好看看自己寫的 mapreduce 程序 ~

13/12/14 13:26:52 INFO streaming.StreamJob: Tracking URL: http://101.rui.com:50030/jobdetails.jsp?jobid=job_201312131904_0030
13/12/14 13:26:53 INFO streaming.StreamJob:  map 0%  reduce 0%
13/12/14 13:27:16 INFO streaming.StreamJob:  map 100%  reduce 100%
13/12/14 13:27:16 INFO streaming.StreamJob: To kill this job, run:
13/12/14 13:27:16 INFO streaming.StreamJob: /usr/local/hadoop/libexec/../bin/hadoop job  -Dmapred.job.tracker=localhost:9001 -kill job_201312131904_0030
13/12/14 13:27:16 INFO streaming.StreamJob: Tracking URL: http://101.rui.com:50030/jobdetails.jsp?jobid=job_201312131904_0030
13/12/14 13:27:16 ERROR streaming.StreamJob: Job not successful. Error: # of failed Map Tasks exceeded allowed limit. FailedCount: 1. LastFailedTask: task_201312131904_0030_m_000000
13/12/14 13:27:16 INFO streaming.StreamJob: killJob...
Streaming Command Failed!

python 做為 mapreduce 執(zhí)行成功后,結果和日志一般是放在你指定的目錄下的,結果是在 part-00000 文件里面~

http://wiki.jikexueyuan.com/project/python-actual-combat/images/56.jpg" alt="pic" />

下面咱們談下,如何入庫和后臺的執(zhí)行

本文出自 “峰云,就她了?!?博客,謝絕轉載!