搭建好环境之后 ,就来跑个简单的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. mysql 终止 存储过程

    [1]如下图所示 有时候,存储过程执行语句中有循环,且已启动.但出于某种原因,我们突然不想让其再继续执行,需要终止其线程. Good Good Study, Day Day UP. 顺序 选择 循环 ...

  2. TLS握手、中断恢复与证书中心的原因

    在双方都拿到随机数A.B.C后,将会使用这三个随机数生成一个对话密钥,然后使用该对话密钥进行对称加密通信,这种方式我们可以看到,安全性取决于随机数C的加密,前面的几个都是明文传的,这里就取决于服务器的 ...

  3. GO流程控制

    Go语言中最常用的流程控制有if和for,而switch和goto主要是为了简化代码.降低重复代码而生的结构,不常用,属于扩展类的流程控制. if else if基本写法 if 表达式1 { 分支1 ...

  4. 软件工程---UML理解

    1.依赖关系和关联关系 1.1依赖关系是调用关系,其又分为全局依赖.参数依赖.局部依赖 1.2关联关系是结构上的关系,按照关联的强弱又具体分为关联关系.聚合关系(整体和部分的组成关系.whole-pa ...

  5. ubuntu 16.04 tip

    参考 1. 安装 python3.6 sudo add-apt-repository ppa:jonathonf/python-3.6  sudo apt-get update sudo apt-ge ...

  6. D2欧拉路,拓扑排序,和差分约束

    第一题:太鼓达人:BZOJ3033 题意:给出k,求一个最长的M位01串,使其从每一个位置向后走k个得到 的M个k位01串互不相同(最后一个和第一个相邻,即是一个环).输出 字典序最小的答案. 2 ≤ ...

  7. 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 ...

  8. JS(JavaScript)的初了解(更新中···)

    1.js介绍 Js全称叫javascript,但不是java,他不仅是是一门前台语言,经过发展,现在也是一门后台语言:而java是后台语言. Js作者是布兰登艾奇. 前台语言:运行在客户端的 后台语言 ...

  9. BZOJ 2759 一个动态树好题(动态树)

    题意 https://www.lydsy.com/JudgeOnline/problem.php?id=2759 思路 每个节点仅有一条有向出边, 这便是一棵基环内向树,我们可以把它在 \(\text ...

  10. 智能合约 helloworld

    windows 平台 所以直接使用Remix在线编译环境 新建hello.sol文件 编辑如下 Remix 右边侧栏 setting 选择合适的编译器版本 这里选择 0.4.19 文件中输入如下内容  ...