Hadoop 是一个开源分布式计算平台。以hadoop 分布式文件系统(HDFS)和MapReduce分布式编程模型为核心的Hadoop 为用户提供了分布式基础架构。HDFS的高容错性,高吞吐量等优点允许用户将 Hadoop部署在低廉的硬件上,形成分布式系统。MapReduce分布式编程模型允许用户在不了解分布式系统底层细节的情况下开发并行应用程序。所以用户可以利用Hadoop轻松组织计算机资源,从而搭建自己的分布式计算平台,并且可以充分利用集群的计算和存储能力,完成海量数据的运算。
HDFS体系结构HDFS采用了主从的结构模型。一个HDFS集群是由一个NameNode,一个SecondaryNode和若干个DataNode组成。其中,NameNode作为主服务器,管理文件系统的命名空间和客户端对文件的访问操作,比如打开,关闭,重命名文件和目录等,也负责数据块到具体DataNode的映射。SecondaryNode用来对日志和镜像进行合并。DataNode管理存储的数据。从内部来看,数据文件被分成若干个数据块,这若干个数据块存放在一组DataNode 上。DataNode负责处理文件系统客户端的文件读写请求,在NameNode的统一调度下进行数据块的创建,删除和复制工作。一种典型的部署场景是集群中的一台机器运行一个NameNode实例,其他机器分别运行一个或多个DataNode实例。NameNode管理所有HDFS元数据,但是用户数据并不会经过NameNode而是直接流向存储数据的DataNode。
MapReduce体系结构基于MapReduce可以将任务分发到上千台机器组成的集群上,并行处理大量的数据集实现Hadoop的并行任务处理功能。MapReduce框架是由一个单独运行在主节点的JobTracker和运行在每个集群从节点的TaskTracker共同组成的。主节点负责调度构成一个作业的所有任务,这些任务分布在不同的从节点上。主节点监控它们的执行情况,并且重新执行之前失败的任务,从节点仅仅负责由主节点指派的任务。当一个Job被提交后,JobTracker接收到提交作业和配置信息之后,就会将配置信息分发给从节点,同时调度任务并监控TaskTracker的执行。
MapReduce编程MapReduce是一种编程模型,用于大规模数据集的并行运算。MapReduce程序将输入划分到不同的节点(一般情况下时不同的主机)上,通过Map将输入键值对映射为一个新的键值对,之后将Map的结果进行合并,提供一个键值对<key , list of value>给Reduce函数,Reduce对相同的key 下的所有的value(list of value)进行处理之后再输出键值对作为最终的结果。
简单说,就是把大数据集分解成许多小的数据集,每个小数据集分别由集群中一台计算机进行处理并且产生中间结果。这些结果再由大量的节点合并,形成最终的结果。
主要任务:编写一个MapReduce对文本中的单词进行计数。也就是统计这个单词在文本中出现的次数。
-
先编写Mapper类
2.编写Reducer类1 package com.hadoop; 2 3 import java.io.IOException; 4 import java.util.StringTokenizer; 5 6 import org.apache.hadoop.io.IntWritable; 7 import org.apache.hadoop.io.LongWritable; 8 import org.apache.hadoop.io.Text; 9 import org.apache.hadoop.mapreduce.Mapper; 10 11 public class Map extends Mapper<LongWritable , Text , Text , IntWritable>{ 12 13 private final static IntWritable one = new IntWritable(1); 14 private Text word = new Text(); 15 16 //对语句分割成单词。设置键值对<word - 1>表示某个单词出现了一次 17 public void map(LongWritable key , Text Value , Context context) throws IOException , InterruptedException{ 18 StringTokenizer itr = new StringTokenizer(value.toString()); 19 while(itr.hasMoreTokens()){ 20 word.set(itr.nextToken()); 21 context.write(word , one); 22 } 23 } 24 }
1 package com.hadoop;
2
3 import java.io.IOException;
4
>> 5 import org.apache.hadoop.io.IntWritable;
>> 6 import org.apache.hadoop.io.Text;
>> 7 import org.apache.hadoop.mapreduce.Reducer;
8
>> 9 public class SumReducer extends Reducer<Text , IntWritable , Text , IntWritable>{
10
>> 11 private IntWritable result = new IntWritable();
12
13 //对<word - iterator of values>进行处理,将迭代器里的值加起来得到sum返回<word - sum>表示一个单词出现了多少次:w
>> 14 public void reduce(Text key , Iterable<IntWritable> values , Context context) throws IOException , InterruptedException{
15 int sum = 0;
>> 16 for(IntWritable val : values){
17 sum += val.get();
18 }
19 result.set(sum);
20 context.write(key , result);
21 }
22 }
- 编写主函数。对任务进行配置。
1 package com.hadoop;
2
3 import java.io.IOException;
4
5 import org.apache.hadoop.conf.Configuration;
6 import org.apache.hadoop.fs.Path;
7 import org.apache.hadoop.io.IntWritable;
8 import org.apache.hadoop.io.Text;
9 import org.apache.hadoop.mapreduce.Job;
10 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
11 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
12
13 public class WordCount{
14
15 public static void main(Stirng[] args) throws IOException , ClassNotFoundException , InterruptedException{
16 //状态信息
17 Configuration conf = new Configuration();
18 //使用方法
19 if(args.length != 2){
>> 20 System.err.println("Usage : WordCount <inFilePath> <outFilePath>");
>> 21 System.exit(2);
22 }
23 //建立job
>> 24 Job job = new Job(conf , "wordCount");
25 //设置执行jar包
26 job.setJarByClass(WordCount.class);
27
28 //指定Mapper类
29 job.setMapperClass(Map.class);
30 //指定Reducer类
31 job.setReducerClass(SumReducer.class);
32 //设置reduce函数输出key的类
33 job.setOutputKeyClass(Text.class);
34 //设置reduce函数输出value的类
35 job.setOutputValueClass(IntWritable.class);
36 //指定输入路径
37 FileInputFormat.addInputPath(job , new Path(args[0]));
38 //指定输出路径
39 FileOutputFormat.setOutputPath(job , new Path(args[1]));
40 //提交任务
41 System.exit(job.waitForCompletion(true) ? 0 : 1);
42 }
43 }
之后对这三个包统一编译打包成jar文件。指定目录。运行。不同版本的api会有区别。但思路基本不变。