MapReduce是一种可用于数据处理的编程模型,该模型比较简单,但用于编写有用的程序并不简单。Hadoop可以运行由各种语言编写的MapReduce程序。MapReduce程序本质上是并行运行的,因此可以将大规模的数据分析任务交给任何一个拥有足够多机器的运营商。MapReduce的优势在于处理大规模数据集。
MapReduce任务过程被分为两个处理阶段:map阶段和reduce阶段。每个阶段都以键/值对作为输入或者输出,并且由程序员选择它们的类型。程序员还需要具体定义两个函数:map函数和reduce函数。
map阶段的输入是原始需要处理的数据,我们可以选择文本格式作为输入格式。map函数是一个数据准备阶段,通过这种方式来准备数据,使reduce函数能够在准备数据上继续处理。map函数的输出经由MapReduce框架处理后,最后被发送到reduce函数。这一处理过程需要根据键值对进行排序和分组。我们要实现一个具体的操作,我们需要三样东西:一个map函数,一个reduce函数和一些用来运行作业的代码。
map函数由Mapper接口实现来表示,后者声明了一个map()方法。该Mapper接口是一个泛型类型,它有四个形参类型,分别制定了map函数的输入键、输入值、输出键和输出值的类型。Hadoop自身提供了一套可优化网络序列化传输的基本类型,而不直接使用Java内嵌的类型,这些类型都可以在org.apache.hadoop.io包中找到。map()方法的输入是一个键和一个值。map()方法还提供了OutputCollector实例用于输出内容的写入。
reduce函数通过Reducer进行类似的定义,针对reduce函数也有四个形式参数类型用于指定其输入和输出类型。reduce函数的输入类型必须与map函数的输出类型相匹配。
JobConf对象指定了作业执行规范,我们可以用它来控制整个作业的运行。在Hadoop集群上运行这个作业时,我们需要将代码打包成一个jar文件,而Hadoop会在集群上分发这个文件。我们无需明确指定jar文件的名称,只需要在JobConf的构造函数中传递一个类,Hadoop将通过该类查找包含该类的jar文件进行找到相关的jar文件。
构造JobConf对象之后,我们需要指定输入和输出数据的路径。调用FileInputFormat类的静态函数addInputPath()来定义输入数据的路径,该路径可以是单个文件、目录(此时将目录下所有文件当做输入)或者符合特定文件模式的一组文件。有函数名可知,我们可以多次调用addInputPath()来实现多路径的输入。
我们通过调用FileOuputFormat类中的静态函数setOutputPath()来指定输出路径,该函数指定了reduce函数输出文件的写入目录。在运行任务前该目录不应该存在,否则Hadoop会报错并拒绝运行该任务。这种预防措施是为了防止数据丢失,一个长时间运行任务的结果被意外的覆盖将会是非常闹人的。
我们通过setMapperClass()和setReduceClass()指定map和reduce类型,setOutputKeyClass()和setOutputValueClass()控制map和reduce函数的输出类型,这两个输出类型往往是相同的。
在设置定义map和reduce函数的类后,便可以开始运行任务。JobClient类的静态函数runJob()会提交作业并且等待完成,最后将其进展情况写到控制台。
如果我们调用hadoop命令的第一个参数是类名,那么Hadoop将会自动启动一个JVM来运行这个类。使用hadoop命令比java命令更加方便,因为前者可以将Hadoop库文件及其依赖关系路径加入到类路径参数中,同时也可以获得Hadoop的配置文件。我们需要定义一个HADOOP_CLASSPATH环境变量用于添加应用程序类的路径,然后由Hadoop脚本来执行相关操作。
为了实现横向扩展(scaling out),我们需要把数据存储在分布式文件系统上,一般为HDFS。
原文地址:http://blog.csdn.net/xinguimeng/article/details/43991215