Hadoop学习笔记(四):Hadoop中的streaming

  Hadoop为MapReduce提供了一个允许你使用除了java以外的语言编写map,reduce函数的API:Hadoop Streaming使用标准流(standard streams)作为Hadoop和应用程序之间传输数据的接口。所以你可以使用任何语言编写map,reduce函数,只要它能够从标准输入流(stdin)中读入数据,以及向标准输出流(stdout)中写输出数据就行。

  Streaming本质上就非常适合处理文本数据。Map输入数据通过stdin传输到map函数中,map函数再一行一行的处理这些输入数据,然后被处理过的以tab分割的键值对被写到stdout中去,reduce函数从stdin中接收到这些map输出(Hadoop框架保证这些map输出是经过关键字排序的),然后把处理后的reduce输出写到stdout中。

 以ruby为例

  以学习笔记(一)中的计算MaxTemperature的程序为例,其Map函数的ruby代码表示如下(即使你像我一样没接触过ruby,你一样可以读懂下面这段代码):

1 #!/usr/bin/env ruby
2 STDIN.each_line do |line|
3   val = line
4   year, temp, q = val[15,4], val[87,5], val[92,1]
5   puts "#{year}\t#{temp}" if (temp != "+9999" && q =~ /[01459]/)
6 end

  这个程序为从stdin中读入的每行数据执行此代码块。这段代码块从每行中抽取出相关的字段(年份,温度和质量),如果温度值有效,就把年份和温度值写入到stdout中去(以tab键分隔开)。

  因为该脚本只是在标准输入和输出上运行,所以最简单的方式就是在unix pipe上进行测试,而不是使用hadoop:

% cat input/ncdc/sample.txt | ch02/src/main/ruby/max_temperature_map.rb
1950 +0000
1950 +0022
1950 -0011
1949 +0111
1949 +0078

  相应的,ruby形式的reduce函数如下所示:

复制代码
 1 #!/usr/bin/env ruby
 2 last_key, max_val = nil, -1000000
 3 STDIN.each_line do |line|
 4   key, val = line.split("\t")
 5   if last_key && last_key != key
 6     puts "#{last_key}\t#{max_val}"
 7     last_key, max_val = key, val.to_i
 8   else
 9     last_key, max_val = key, [max_val, val.to_i].max
10   end
11 end
12 puts "#{last_key}\t#{max_val}" if last_key
复制代码

  同样的,这段代码迭代从stdin中读入的每一行,但是我们必须为当前正在处理的每一个key group保存一些数据。在这个例子中,key是年份值,我们把上一次处理过的年份值last_key和迄今为止对应的该key group中最大的温度值max_val存储下来。MapReduce框架会确保这些key值是经过排序的,所以当我们遇到一个不同的key值时,说明上一个key group已经处理完了,所保存的最大温度值max_val就是该key group最大的温度值。对比一下java实现,我们可以发现,java API会自动的为你分组,而在ruby中你不得不自己确定key group的界限。

  对于每一行,我们抽取出年份和温度值,如果我们已经处理完了一组key-value pair(last_key && last_key != key),我们就把last_key和max_value(仍然以tab键分开)写入到stdout中去,然后重新设置last_key,max_value为对应的新值。如果还没有处理完某个key group,我们就只是更新下当前last_key所对应的max_value。现在我们仍然用unix pipe来模拟下整个mapreduce过程:

% cat input/ncdc/sample.txt | ch02/src/main/ruby/max_temperature_map.rb | \
sort | ch02/src/main/ruby/max_temperature_reduce.rb
1949 111
1950 22

  可以看到,这次输出跟java对应的输出是一样的,现在我们使用Hadoop来运行一下。由于hadoop命令不支持streaming选项,所以你必须通过jar选项声明要处理streaming 的streaming jar文件。如下所示:

% hadoop jar $HADOOP_INSTALL/contrib/streaming/hadoop-*-streaming.jar \
-input input/ncdc/sample.txt \
-output output \
-mapper ch02/src/main/ruby/max_temperature_map.rb \
-reducer ch02/src/main/ruby/max_temperature_reduce.rb

  如果是在一个较大的集群上运行改程序,我们可以使用-combiner选项来声明一个combiner(关于combiner的内容请参看学习笔记(三))。早前的版本combiner可能限定于java代码实现,但在1.x以后的版本中,combiner可以是任意的streaming命令。如下所示:

% hadoop jar $HADOOP_INSTALL/contrib/streaming/hadoop-*-streaming.jar \
-input input/ncdc/all \
-output output \
-mapper "ch02/src/main/ruby/max_temperature_map.rb | sort |
ch02/src/main/ruby/max_temperature_reduce.rb" \
-reducer ch02/src/main/ruby/max_temperature_reduce.rb \
-file ch02/src/main/ruby/max_temperature_map.rb \
-file ch02/src/main/ruby/max_temperature_reduce.rb

  在本例中,我们指定输入文件为一个目录(-input input/ncdc/all),这样就把该目录下的所有文件读入mapper中了(在本例中此目录下是两个.gz文件,也就是gzip的压缩文件:1901.gz,1902.gz)。其中-file选项用来说明要拷贝到集群上的文件(如果是在单例模式下运行就不需要这么做了)。值得注意的是,此例中的-mapper选项同时指明了mapper和combiner(也就是max_temperature_reduce.rb,还记得吗,在学习笔记(三)中我们知道java代码的combiner跟reducer是同一实现)

   以Python为例

  熟悉python的同学可以参考一下python下map和reduce函数的代码::

复制代码
1 #!/usr/bin/env python
2 import re
3 import sys
4 for line in sys.stdin:
5   val = line.strip()
6   (year, temp, q) = (val[15:19], val[87:92], val[92:93])
7   if (temp != "+9999" and re.match("[01459]", q)):
8     print "%s\t%s" % (year, temp)
复制代码
复制代码
 1 #!/usr/bin/env python
 2 import sys
 3 (last_key, max_val) = (None, -sys.maxint)
 4 for line in sys.stdin:
 5   (key, val) = line.strip().split("\t")
 6   if last_key and last_key != key:
 7     print "%s\t%s" % (last_key, max_val)
 8     (last_key, max_val) = (key, int(val))
 9   else:
10     (last_key, max_val) = (key, max(max_val, int(val)))
11 if last_key:
12   print "%s\t%s" % (last_key, max_val)
复制代码

  执行测试脚本命令为:

% cat input/ncdc/sample.txt | ch02/src/main/python/max_temperature_map.py | \
sort | ch02/src/main/python/max_temperature_reduce.py
1949 111
1950 22

转载请注明出处:http://www.cnblogs.com/beanmoon/archive/2012/12/07/2807759.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hadoop是一个开源的分布式计算框架,可用于大数据的存储和处理。它采用了分布式文件系统(HDFS)和分布式计算框架(MapReduce),能够将大数据分割成小的数据块,并在集群的多台计算机上并行处理这些数据块。 HDFS是Hadoop的分布式文件系统,它将大文件切分为多个数据块,并将这些数据块存储在集群的多个计算机上。HDFS使用主从架构,其NameNode负责管理文件系统的元数据,而多个DataNode负责实际存储数据。HDFS具有高容错性,能够自动复制数据块以保证数据的可靠性。 MapReduce是Hadoop的分布式计算框架,它通过将计算任务划分为多个Map和Reduce阶段来进行并行计算。Map阶段将输入数据切分为多个独立的小任务,并在集群的多个计算机上并行执行。Reduce阶段将Map阶段的输出合并并进行聚合计算。MapReduce具有自动并行化、容错性和可扩展性等优点,能够高效地处理大规模数据集。 在学习Hadoop时,首先要了解Hadoop的核心组件,包括HDFS和MapReduce。然后,需要学习Hadoop的架构和工作原理,理解Hadoop如何实现分布式存储和计算。接下来,需要学习Hadoop的安装和配置,包括在单机和集群环境下的安装和配置过程。此外,还需要学习Hadoop的命令行工具和管理工具,以及Hadoop的API和编程模型。 在实际使用Hadoop时,需要掌握Hadoop的常用操作和管理技巧,如如何上传和下载文件、如何执行MapReduce作业、如何监控和管理Hadoop集群等。同时,需要学习Hadoop的优化技术和调优方法,以提高Hadoop集群的性能和效率。 总之,对于Hadoop学习,除了理解其基础知识和工作原理外,还需要熟悉其常用操作和管理技巧,以及灵活运用Hadoop来解决实际的大数据问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值