搭建好环境之后 ,就来跑个简单的Mapreduce试试看吧。这个比第一课难多了,需要多多练习并熟练掌握。

需要编写py脚本以及shell脚本, 所以需要学习Python和Linux的Shell编程。

虽然现在可以照抄老师的代码,但是代码有些方面还不太懂,更不能够理解透彻。所以,需要继续学习python

以下是笔记,  bash shell和py都写在同一个文本文件中,仅以空行隔开:

# MapReduce基础
# 海量都能处理, GTP级都能处理,理论上是没有瓶颈的.
# 一次性同时处理整个数据集, 数据必须一次全进来,
# 批处理方式, 大数据输入,大批数据输出.
#之所以可以用多种语言来开发,主要是有Hadoop Streaming的存在
#使用python来MR比较方便.
############################ word count 第一版############################
vim map.py
#!/etc/bin/python
import sys for line in sys.stdin:
ss = line.strip().split(' ')
for word in ss:
print '\t'.join([word.strip(),""]) cat .txt | python map.py cat word2 | grep --color -w this # 查找并显示文件中this
cat word2 | grep --color -wo this # 只显示this
cat word2 | grep --color -wo this | wc -l # 显示this数量 vim reduce.py
#!/etc/bin/python
import sys cur_word = None
sums = for line in sys.stdin:
ss = line.strip().split('\t')
if len(ss) !=:
continue
word = ss[].strip()
cnt = ss[].strip() if cur_word == None:
cur_word = word
if cur_word != word:
print '\t'.join([cur_word, str(sums)]) cur_word = word
sums =
sums += int(cnt) print '\t'.join([cur_word, str(sums)]) # 本地测试程序流程, 通过再继续
cat word2 | python map.py | sort -k | python reduce.py

下面把它放到hdfs上试试:

可以先把文本文件上传到hdfs, 如果脚本执行时发生错误:-bash: ./run.sh: /bin/bash^M: bad interpreter: No such file or directory

原因是windows编辑的sh文件,复制到Linux中执行,则格式不对。可用 vim打开,然后  :set ff=unix 再保存退出

####################### 为Hadoop 准备shell脚本
vim run.sh
#!/bin/bash
#引入 streaming Jar包
STREAM_JAR_PATH="/usr/local/src/hadoop-2.7.5/share/hadoop/tools/lib/hadoop-streaming-2.7.5.jar"
# HDFS上要处理的文件
INPUT_FILE_PATH_1="/word2"
OUTPUT_PATH="/output"
#先删除原有的输出路径,如果存在,会报错
/usr/local/src/hadoop-2.7./bin/hdfs dfs -rm -r $OUTPUT_PATH

# 创建源文件路径
/bigdata/hadoop-2.7.5/bin/hdfs dfs -mkdir /test
# 上传文本文件
/bigdata/hadoop-2.7.5/bin/hdfs dfs -put 1.txt /test

/usr/local/src/hadoop-2.7./bin/hadoop jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH_1 \
-output $OUTPUT_PATH \
-mapper "python map.py" \
-reducer "python reduce.py" \
-jobconf "mapred.reduce.tasks=2" \
-file ./map.py \
-file ./reduce.py
# mapred.reduce.tasks= 指定reduce个数, 默认为1,这个参数只是参考,不是很准. 受到数据源大小以及分片的影响 .
# -jobconf mapred.job.name="Digital_log_count" 为job指定名称
# -cacheFile 向计算节点分发HDFS文件
# -cacheArchive 向计算节点分发HDFS压缩文件
######################### 执行上面的脚本 , 等待结果.
hdfs dfs -get /output/part-
cat word2 | python map.py | sort -k1 |python reduce.py > local.data
#对比一下结果
cat local.data | sort > local.data.
cat part- | sort > cluster.data
md5sum local.data.
md5sum cluster.data
#或者使用cmp命令, 结果是0就表示一致.
cmp local.data. cluster.data
echo $?

另一个版本的,白名单版的mapreduce

############################ word count 第二版只统计白名单 (white_list)############################
vim map.py
#!/etc/bin/python
import sys def read_local_file_func(f):
word_set = set()
file_in = open(f, 'r')
for line in file_in:
word = line.strip()
word_set.add(word)
return word_set def mapper_func(white_list_fd):
word_set = read_local_file_func(white_list_fd) for line in sys.stdin:
ss = line.strip().split(' ')
for s in ss:
word = s.strip()
if word != "" and (word in word_set):
print "%s\t%s" % (s, ) if __name__ == "__main__":
module = sys.modules[__name__]
func = getattr(module, sys.argv[])
args = None
if len(sys.argv) > :
args = sys.argv[:]
func(*args) vim reduce.py
#!/etc/bin/python
import sys def reduer_func():
current_word =None
count_pool = []
sum = for line in sys.stdin:
word, val = line.strip().split('\t') if current_word ==None:
current_word = word if current_word != word:
for count in count_pool:
sum += count
print "%s\t%s" % (current_word, sum)
current_word = word
count_pool = []
sum = count_pool.append(int(val)) for count in count_pool:
sum += count
print "%s\t%s" % (current_word, str(sum)) if __name__ == "__main__":
module = sys.modules[__name__]
func = getattr(module, sys.argv[])
args = None
if len(sys.argv) > :
args = sys.argv[:]
func(*args) vim run.sh
#!/bin/bash
STREAM_JAR_PATH="/usr/local/src/hadoop-2.7.5/share/hadoop/tools/lib/hadoop-streaming-2.7.5.jar" INPUT_FILE_PATH_1="/word2"
OUTPUT_PATH="/output"
#先删除原有的输出路径,如果存在,会报错
/usr/local/src/hadoop-2.7./bin/hdfs dfs -rm -r $OUTPUT_PATH #step
/usr/local/src/hadoop-2.7./bin/hadoop jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH_1 \
-output $OUTPUT_PATH \
-mapper "python map.py mapper_func white_list" \
-reducer "python reduce.py reduer_func" \
-jobconf "mapred.reduce.tasks=2" \
-file ./map.py \
-file ./reduce.py \
-file ./white_list #执行本地测试与hdfs测试 ############################ 结束: word count 第二版只统计白名单 (white_list)############################

老师在课堂上提到的2个知识点:

# Streaming 优点: 开发效率高, 程序运行效率高, 便于平台进行资源控制
#Streaming框架中通过limit等方式可以灵活地限制应用程序使用的内存资源 # Streaming缺点: 两次数据copy和解析(分割),带来一定的开销
#Streaming不能直接处理二进制数据,如果要处理二进制的数据,比较好的方法是将二进制的key和value进行base64的编码转化成文本
python
import base64
base64.b64encode('abcdefg')
base64.b64decode('YWJjZGVmZw==') ### jieba 中文分词
# wget --no-check-certificate https://pypi.python.org/packages/71/46/c6f9179f73b818d5827202ad1c4a94e371a29473b7f043b736b4dab6b8cd/jieba-0.39.zip
file jieba-0.39.zip
unzip jieba-0.39.zip
### 压缩解压命令
gzip .txt
gunzip .txt.gz

两种文件的分发与打包:

#############################    文件分发与打包(-cacheFile)
#如果本地配置和数据很大的时候,需要提前上传到HDFS目录上.
#如果文件(如字典文件)存放在HDFS中,希望计算时在每个计算节点上将文件当作本地文件处理,可以使用-cacheFile hdfs://host:port/path/to/file#linkname选项在计算节点缓存文件.
# Streaming程序通过./linkname访问文件 vim run.sh
HADOOP_CMD="/usr/local/src/hadoop-2.7.5/bin/hadoop"
STREAM_JAR_PATH="/usr/local/src/hadoop-2.7.5/share/hadoop/tools/lib/hadoop-streaming-2.7.5.jar" INPUT_FILE_PATH_1="/The_Man_of_property.txt"
OUTPUT_PATH="/output_cachefile_broadcast" $HADOOP_CMD fs -rm -r -skipTrash $OUTPUT_PATH #step
$HADOOP_CMD jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH_1 \
-output $OUTPUT_PATH \
-mapper "python map.py mapper_func ABC" \
-reducer "python red.py reducer_func" \
-jobconf "mapred.reduce.tasks=2" \
-jobconf "mapred.job.name=cachefile_demo" \
-cacheFile "hdfs://master:9000/white_list.txt#ABC" \
-file "./map.py" \
-file "./red.py" \ #ABC是文件别名,代替white_list.txt 另外,map.py和reduce.py可以只用上面第一例的,不必更改, 因为只是文件分发方式变了.
# tasks=2的时候,也可能在结果产生空文件, 因为hash到key的时候,分到一个文件里了. # map的输出也就是中间结果启用压缩, 主要是为了减少shuffle过程中的网络传输数据量
-jobconf "mapred.compress.map.output=true" \
-jobconf "mapred.map.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec" \
# 输出时压缩, 减少输出结果占用HDFS存储
-jobconf "mapred.output.compress=true" \
-jobconf "mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec" \ ############################# 文件分发与打包(-cacheArchive)
#如果要分发的文件有目录结构,可以先将整个目录打包,上传到HDFS,再用-cacheArchive hdfs://host:port/path/to/archivefile#linkname 分发压缩包
#有2个白名单文件, white_list_1, white_list_2 可以打包到一起
tar zcvf w.tar.gz white_list_* #可以复制到别的目录解压验证
hdfs dfs -put w.tar.gz / vim run.sh
HADOOP_CMD="/usr/local/src/hadoop-2.7.5/bin/hadoop"
STREAM_JAR_PATH="/usr/local/src/hadoop-2.7.5/share/hadoop/tools/lib/hadoop-streaming-2.7.5.jar" INPUT_FILE_PATH_1="/The_Man_of_property.txt"
OUTPUT_PATH="/output_cachefile_broadcast" $HADOOP_CMD fs -rm -r -skipTrash $OUTPUT_PATH #step
$HADOOP_CMD jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH_1 \
-output $OUTPUT_PATH \
-mapper "python map.py mapper_func WH.gz" \
-reducer "python red.py reducer_func" \
-jobconf "mapred.reduce.tasks=2" \
-jobconf "mapred.job.name=cachefile_demo" \
-cacheArchive "hdfs://master:9000/w.tar.gz#WH.gz" \
-file "./map.py" \
-file "./red.py" \ vim map.py
#!/usr/bin/python
import os
import sys
import gzip def get_file_handler(f):
file_in = open(f, 'r')
return file_in def get_cachefile_handlers(f):
f_handlers_list = []
if os.path.isdir(f):
for fd in os.listdir(f):
f_handlers_list.append(get_file_handler(f + '/' +fd))
return f_handlers_list def read_local_file_func(f):
word_set = set()
for cachefile in get_cachefile_handlers(f):
for line in cachefile:
word = line.strip()
word_set.add(word)
return word_set def mapper_func(white_list_fd):
word_set = read_local_file_func(white_list_fd) for line in sys.stdin:
ss = line.strip().split(' ')
for s in ss:
word = s.strip()
if word != "" and (word in word_set):
print "%s\t%s" % (s,) if __name__ == "__main__":
module = sys.modules[__name__]
func = getattr(module, sys.argv[])
args = None
if len(sys.argv) > :
args = sys.argv[:]
func(*args) vim reduce.py
#!/etc/bin/python
import sys def reduer_func():
current_word =None
count_pool = []
sum = for line in sys.stdin:
word, val = line.strip().split('\t') if current_word ==None:
current_word = word if current_word != word:
for count in count_pool:
sum += count
print "%s\t%s" % (current_word, sum)
current_word = word
count_pool = []
sum = count_pool.append(int(val)) for count in count_pool:
sum += count
print "%s\t%s" % (current_word, str(sum)) if __name__ == "__main__":
module = sys.modules[__name__]
func = getattr(module, sys.argv[])
args = None
if len(sys.argv) > :
args = sys.argv[:]
func(*args)

老师给的不想开发代码,直接套模板的MR方案:

######################### 不想开发代码,只做单reduce, 如下是配置文件以及2个py脚本。
vim run.sh
set -e -x HADOOP_CMD="/usr/local/src/hadoop-2.7.5/bin/hadoop"
STREAM_JAR_PATH="/usr/local/src/hadoop-2.7.5/share/hadoop/tools/lib/hadoop-streaming-2.7.5.jar" INPUT_FILE_PATH_A="/a.txt"
INPUT_FILE_PATH_B="/b.txt" OUTPUT_SORT_PATH="/output_sort" $HADOOP_CMD fs -rm -r -skipTrash $OUTPUT_SORT_PATH #step
$HADOOP_CMD jar $STREAM_JAR_PATH \
-input $INPUT_FILE_PATH_A,$INPUT_FILE_PATH_B \
-output $OUTPUT_SORT_PATH \
-mapper "python map_sort.py" \
-reducer "python red_sort.py" \
-file "./map_sort.py" \
-file "./red_sort.py" \
-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \
-jobconf mapred.output.key.comparator.class=org.apache.hadoop.mapred.lib.KeyFieldBasedComparator \
-jobconf stream.num.map.output.key.fields= \
-jobconf stream.map.output.field.separator='^I' \
-jobconf map.output.key.field.separator='^I' \
-jobconf mapred.text.key.partitioner.options="-k1,1" \
-jobconf mapred.text.key.comparator.options="-k1,1n" \
-jobconf mapred.reduce.tasks= #上面的几行参数缺一个都不行.
#下面这2行按第1列的数值去partition, 保证它分到哪个桶,保证它这数据能分到哪个reduce上处理. key和partition是不相等的,效果是按第1列数值去partition,按第2列去排序.
# -jobconf stream.num.map.output.key.fields= \
# -jobconf num.key.fields.for.partition= \
#而下面这一行代替了partition
# -jobconf mapred.text.key.partitioner.options="-k1,1" \ #第1列开始,1列结束,也就是将第1列作为partition
# -jobconf mapred.text.key.comparator.options="-k1,1n" \ #按第1到1的列排序, n是将其转换为数值型. ### 最少代码的自然数排序,map只是将字符串解析一下。基本没做处理。
vim map_sort.py
#!/etc/bin/python
import sys for line in sys.stdin:
ss = line.strip().split('\t')
key = ss[]
val = ss[] print "%s\t%s" % (key, val) ### reduce读什么出什么,基本没做处理。
vim red_sort.py
#!/etc/bin/python
import sys for line in sys.stdin:
print line.strip()

以及MR join

########################## MapReduce Join   三个map文件, 前2个处理完成,合并到第3个mapreduce中
vim map_a.py
#!/usr/bin/python import sys for line in sys.stdin:
ss = line.strip().split('^I') key = ss[]
val = ss[] print "%s\t1\t%s" % (key,val) # 示例数据 a.txt
aaa1
aaa2
aaa3
aaa4
aaa5
aaa6
aaa7
aaa8
aaa9
aaa10 vim map_b.py
#!/usr/bin/python import sys for line in sys.stdin:
ss = line.strip().split('^I') key = ss[]
val = ss[] print "%s\t2\t%s" % (key,val) # 示例数据 b.txt
aaa1 hadoop
aaa2 hadoop
aaa3 hadoop
aaa4 hadoop
aaa5 hadoop
aaa6 hadoop
aaa7 hadoop
aaa8 hadoop
aaa9 hadoop
aaa10 hadoop #### reduce_join脚本 这段代码可能有问题。
vim red_join.py
#!/usr/bin/env python import sys val_1 = []
for line in sys.stdin:
key, flag, val = line.strip().split('\t') if flag =='':
val_1.append(val)
elif flag == '' and val_1 != "" :
val_2 = val for v in val_1:
print "%s\t%s\t%s" % (key, v, val_2)
val_1 = [] # 上述这段代码可能有问题,要求对输入的数据符合格式

Hadoop学习笔记02_MapReduce练习的更多相关文章

  1. Hadoop学习笔记—22.Hadoop2.x环境搭建与配置

    自从2015年花了2个多月时间把Hadoop1.x的学习教程学习了一遍,对Hadoop这个神奇的小象有了一个初步的了解,还对每次学习的内容进行了总结,也形成了我的一个博文系列<Hadoop学习笔 ...

  2. Hadoop学习笔记(7) ——高级编程

    Hadoop学习笔记(7) ——高级编程 从前面的学习中,我们了解到了MapReduce整个过程需要经过以下几个步骤: 1.输入(input):将输入数据分成一个个split,并将split进一步拆成 ...

  3. Hadoop学习笔记(6) ——重新认识Hadoop

    Hadoop学习笔记(6) ——重新认识Hadoop 之前,我们把hadoop从下载包部署到编写了helloworld,看到了结果.现是得开始稍微更深入地了解hadoop了. Hadoop包含了两大功 ...

  4. Hadoop学习笔记(2)

    Hadoop学习笔记(2) ——解读Hello World 上一章中,我们把hadoop下载.安装.运行起来,最后还执行了一个Hello world程序,看到了结果.现在我们就来解读一下这个Hello ...

  5. Hadoop学习笔记(5) ——编写HelloWorld(2)

    Hadoop学习笔记(5) ——编写HelloWorld(2) 前面我们写了一个Hadoop程序,并让它跑起来了.但想想不对啊,Hadoop不是有两块功能么,DFS和MapReduce.没错,上一节我 ...

  6. Hadoop学习笔记(3)——分布式环境搭建

    Hadoop学习笔记(3) ——分布式环境搭建 前面,我们已经在单机上把Hadoop运行起来了,但我们知道Hadoop支持分布式的,而它的优点就是在分布上突出的,所以我们得搭个环境模拟一下. 在这里, ...

  7. Hadoop学习笔记(2) ——解读Hello World

    Hadoop学习笔记(2) ——解读Hello World 上一章中,我们把hadoop下载.安装.运行起来,最后还执行了一个Hello world程序,看到了结果.现在我们就来解读一下这个Hello ...

  8. Hadoop学习笔记(1) ——菜鸟入门

    Hadoop学习笔记(1) ——菜鸟入门 Hadoop是什么?先问一下百度吧: [百度百科]一个分布式系统基础架构,由Apache基金会所开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序. ...

  9. Hadoop学习笔记(两)设置单节点集群

    本文描写叙述怎样设置一个单一节点的 Hadoop 安装.以便您能够高速运行简单的操作,使用 Hadoop MapReduce 和 Hadoop 分布式文件系统 (HDFS). 參考官方文档:Hadoo ...

随机推荐

  1. 一定要知道的,那些Linux操作命令

    一定要知道的,那些Linux基本操作命令(一) 目录 1.文件和目录操作命令 2.用户和用户组操作命令 3.vim编辑器操作命令 4.打包和解压操作命令 5.系统操作命令 为什么要学习linux? 1 ...

  2. 论文笔记【一】Chinese NER Using Lattice LSTM

    论文:Chinese NER Using Lattice LSTM 论文链接:https://arxiv.org/abs/1805.02023 论文作者:Yue Zhang∗and Jie Yang∗ ...

  3. js中prototype,constructor的理解

    连看4篇前辈的文章,记录一些知识点 Javascript继承机制的设计思想 Javascript 面向对象编程(一):封装 Javascript面向对象编程(二):构造函数的继承 Javascript ...

  4. sed 正则的一个小问题

    有一段类似以下的文本 aabbccc test[3307]112323553-66778tp aooppx69tp ooppsg aabbccc test[3307]1127233-6674tp bo ...

  5. Mysql error 1317导致从库复制断开

    环境 :Percona Server for MySQL 5.5.18 1. 报错日志: 171212 19:59:58 [ERROR] Slave SQL: Query partially comp ...

  6. Windows安装MySQL5.7.23 zip包

    工欲善必先利其器 # 环境: Win7旗舰版 + MySQL5.7.23 # 用到的命令: mysqld --initialize -- 初识化 mysqld --install -- 添加到Wind ...

  7. hdoj1905 Pseudoprime numbers (基础数论)

    Problem Description Fermat's theorem states that for any prime number p and for any integer a > 1 ...

  8. 剑指offer(40)数组中只出现一次的数字

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 题目分析 第一种方法:使用js中的indexOf()和lastIndexOf(),只要两个相等, ...

  9. Python将list中的string批量转化成int/float

    data = ['] data = map(eval, data) print data 输出:[1, 3.2, 2] 但是在Python3下我们输入: ls=[1,2,3] rs=map(str,l ...

  10. BottomNavigationBar + BottomNavigationBarItem导航的另外一种用法

    import 'package:flutter/material.dart'; import 'News.dart'; import 'Video.dart'; import 'Chat.dart'; ...