一、mapreduce的编程思想:


简述:MapReduce是分布式运算程序的编程框架是用户开发“基于hadoop的数据分析应用的和新框架”。


MR的核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个hadoop集群上。


引入MR框架后,开发人员可以将绝大部分工作集中在业务逻辑的开发上,而将分布式计算中的复杂性交由框架来处理。(每一次map,reduce程序的调用)




①MR框架的结构:一个MapReduce程序在分布式运行时有三类实例进程


a.MRAppMaster:负责整个程序的过程调度及状态协调;


b.MapTask:负责map阶段的数据处理流程;


c.ReduceTask:负责reduce阶段的数据处理流程。


②流程示意图的解释:MapTask在datanode中读取文件(详见Hdfs的读取数据机制);若干个MapTask每读取一行,就调用一次map程序,并将kv对输出;SHUFFLE过程;ReduceTask将MapTask输出的kv对进行迭代综合计算,按照相同k类聚合后输出。Map和Reduce这两个过程的调度及状态协调都交给MRAppMaster来运行。具体见流程解析


一个reduceTask会关联若干个mapTask,按k值聚合。partitioner是maptask输出后分区,reducetask输出即是分多个文件




二、word count编程实例分析:


关于Java


for循环的遍历补充


涉及到的补充对象:Configuration;Job;FileIntputFormat,FileOutputFormat;迭代器Iterable;IntWritable;Text;Context 只有序列化后才能在网络上传输




备注:



mapred是旧的API;



mapreduce是新的API,这里用到的API都要使用最新的mapreduce的api。




以Wordcount为例来熟悉MR程序的编写规范:


首先明确用户编写的程序分为三个部分:Mapper;Reducer;Driver




①编写Mapper:MR框架每传一行数据就被调用一次该map方法。


a:让主类继承Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>


定义四个泛型的类型


KEYIN : LongWritable ;   <泛型含义补充>


VALUE : Text ;


KEYOUT : Text ;              


VALUEOUT : IntWritable ;




b:覆盖map方法  protected void map(LongWritable key ,Text value ,Context context);  主要完成取出单词。


key:这一行数据起始点在文件中的偏移量;


value:这一行的内容


主要完成:


b.1:value.toString().split(" ");取出该行的字符串,通过split()方法以空格区分出各单词,储存在字符串数组String[] words中。


b.2:遍历数组,取出单词写入context。写入的格式是<word,1>。


 for(String word:words){


    context.write(new Text(word),new IntWritable(1));


  }




②编写Reducer:Reducer类是按照key来执行的,有一个key就调用一次reduce方法。


a:让主类继承Reduce<KEYIN, VALUEIN, KEYOUT, VALUEOUT>四个参数分别是:Text, IntWritable, Text, IntWritable


输入的KV是每个maptask输出的<单词.1>;输出的kv是reducetask任务输出的<单词,n>。




b: 重写reduce(Text key,Iterable<IntWritable> values,Context context)方法;reduce方法具体执行的任务就是将输入的kv对,迭代累加统计即可。




b.1  for(IntWritable value:values)//遍历某个key下的迭代器values将value.get()累加即可得到该key的出现次数,在本例中也就是单词的出现次数。




b.2: 执行context.write(key,new IntWritable(count));方法。按照<单词,n>的格式写入context中。






③编写Driver类:相当于yarn集群的客户端,封装mr程序的相关运算参数,指定jar包等


a:main函数,此过程执行在main函数中。


b:新建Job作业的对象Job.getInstance(new Configuration);


c:指定本jar包的Driver类  job.setJarByClass(wordcountDriver.class);                 


设置三个类


d:指定本job要使用的Mapper类和Reducer类。              job.setMapperClass(wordcountMapper.class);      job.setRuedcerClass(wordcountReducer.class);




设置Map-->Reduce的中间的kv数据类型


e:指定Mapper输出数据的kv类型。                                job.setMapOutputKeyClass(Text.class);                  job.setMapOutputValueClass(IntWritable.class);


                


设置最终输出的结果的kv数据类型,基本同上


d:指定最终输出的数据的kv类型(Reducer类),                job.setOutputKeyClass(Text.class);                         job.setOutputValueClass(IntWritable.class);




 设置输入文件路径,输出结果保存路径


f:指定job要处理的数据所在的位置和处理后保存的位置。


FileInputFormat.setInputPaths(job,"hdfs://host:9000/wordcount/data/a.txt");


FileOutputFormat.setOutputPaths(job,    new Paths("hdfs://host:9000/wordcount/data/output/"));


g:提交,退出。job.waitForCompletion(true)


………………………………………………………………………………Job.set一共九个类………………………………………………………………………………………………………………


④将工程文件打包jar:  


host上执行start-dfs.sh;start-yarn.sh;将jar文件拖到host中;


原则上放在那个服务器上都行,因为是用yarn来操作hdfs上的文件。


host:8088 来查看操作的记录


 hadoop jar wordcount.jar testMR.WordcountDriver






四、关于切片


切片客户端来操作,切片数就是maptask数相同的,跟block无关。


①任务切片,是逻辑划分。block块是物理切片。二者无关。


②一个切片对应一个maptask,文件小按照block的大小来读文件。效率低。


③一个job的map阶段并行度由客户端在提交job时决定;而客户端对map阶段并行度的规划的基本逻辑为:将待处理数据执行逻辑切片(即按照一个特定切片大小,将待处理数据划分成逻辑上的多个split),然后每一个split分配一个mapTask并行实例处理这段逻辑及形成的切片规划描述文件,由FileInputFormat实现类的getSplits()方法完成,



通过分析源码,在FileInputFormat中,计算切片大小的逻辑:切片可调

Math.max(minSize, Math.min(maxSize,blockSize));



minsize:默认值:1

配置参数: mapreduce.input.fileinputformat.split.minsize

maxsize:默认值:Long.MAXValue

配置参数:mapreduce.input.fileinputformat.split.maxsize

blocksize



因此,默认情况下,切片大小=blocksize   比blocksize小则切片小;比blocksize大则切片大

maxsize(切片最大值):

maxsize参数如果调得比blocksize小,则会让切片变小,而且就等于配置的这个参数的值

minsize (切片最小值):

minsiz参数调的比blockSize大,则可以让切片变得比blocksize还大



剩余数据大小不超过1.1倍算作进一个maptask
hdfs  dfsadmin  -report   //hdfs的容量信息
appmaster根据job描述信息计算maptask的数量,map和reduce运行过程中都是Mrappmaster管理






五、编程规范:


(1)用户编写的程序分成三个部分:Mapper,Reducer,Driver(提交运行mr程序的客户端)

(2)Mapper的输入数据是KV对的形式(KV的类型可自定义)

(3)Mapper的输出数据是KV对的形式(KV的类型可自定义)

(4)Mapper中的业务逻辑写在map()方法中

(5)map()方法(maptask进程)对每一个<K,V>调用一次

(6)Reducer的输入数据类型对应Mapper的输出数据类型,也是KV

(7)Reducer的业务逻辑写在reduce()方法中

(8)Reducetask进程对每一组相同k的<k,v>组调用一次reduce()方法

(9)用户自定义的Mapper和Reducer都要继承各自的父类

(10)整个程序需要一个Drvier来进行提交,提交的是一个描述了各种必要信息的job对象

 备注:两种实现方法(已知)。一种是建立三个类;另一种是在一个主类中建立两个静态类实现mapper和reducer。主类中实现main方法,配置Driver类。




六、常见错误:



1、windows下的java编译版本不能高于服务器下的java版本,在eclipse的java complier下修改1.7



2、出现type mismatch,意思是输入和输出的数据类型不同;一般是没有删除掉map和reduce的super()方法。



3、输出结果路径--new Path(" ");必须是新路径



4、工程、输入文件、输出文件的目录分好,不要弄混。无用文件删除。



5、做实例,先打开dfs后打开yarn。否则会出现retrying的事情


6、使用hadoop找不到命令时,及时source /etc/profile  即可!!


7、java编程:输入输出路径,导入包,main输入参数,






七、总体运算步骤:


启动服务器-->host: start-dfs.sh;start-yarn.sh-->Java编程细节-->将项目打包.jar上传到host上-->host上执行:hadoop jar xxx.jar  pacakge.class  -->hadoop fs -cat/output/part-r-00000来查看输出结果。    (此为整个的云计算的过程)




八、关于Job:


Job的所有配置:处理切片规划-->获取切片list生成job.split


Job参数写到一个文件-->Job.xml


将Job打包-->xx.jar