是一个分布式的编程框架,MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。
private IntWritable key = new IntWritable();
key.set(java_value);
new intWritable(1);
int value = key.get();
该类中的步骤是使用hadoop框架的核心,这8个步骤是写死的,无法更改,具体为:
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
//1.获取一行
// atguigu atguigu
String line = value.toString();
//2.切割
//atguigu
//atguigu
String[] words = line.split(" ");
//3.循环写出
for (String word : words) {
//封装outKey
context.write(new Text(word),new IntWritable(1));
}
}
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
int sum = 0;
//atguigu(1,1)
//累加
for (IntWritable value : values) {
sum += value.get();
}
//写出
context.write(key, new IntWritable(sum);//注意
}
在处理大数据时,不要在循环中new对象,创建对象是很消耗资源的。可以使用ctrl + alt + F
将这两个变量提升为全局变量,作为Reducer类的属性值。但其实还有更好的方法,可以使用Mapper类中的setup()方法来实现该需求。该方法是框架里面原本就设定好的方法,在map阶段前只会执行1次。
private Text outKey;
private IntWritable outValue;
@Override
protected void setup(Mapper<LongWritable, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException {
outKey = new Text();
outValue = new IntWritable(1);
}
该类的写法基本上是固定的,不同需求只需要在此基础上修改一下map和reduce业务类即可。
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
//1.获取Job
Configuration conf = new Configuration();
Job job = Job.getInstance();
//2.设置jar包路径,绑定driver类
job.setJarByClass(WordCountDriver.class);
//3.关联mapper和reducer
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
//4.设置map的kv类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//5.设置最终输出的kv类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6.设置输入路径和输出路径
FileInputFormat.setInputPaths(job, new Path("D:\\inputOutput\\input\\wordcount"));
FileOutputFormat.setOutputPath(job, new Path("D:\\inputOutput\\output\\output666"));
//7.提交job
job.waitForCompletion(true);
}
//6.设置输入路径和输出路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
jar 包名 数据输入路径 数据输出路径
可以直接在window中的IDEA中发送任务到Linux集群中,但配置方式较为烦琐,生产环境中使用该方法的人较少。
序列化目的是将内存的对象放进磁盘中进行保存,序列化实际上是为了传输对象中的属性值,而不是方法。序列化本质上是一种数据传输技术,IO流。
总结:java序列化是一个比较重的序列化,序列化的内容很多,比如属性+校验+血缘关系+元数据。
特点: 轻量化,只有属性值和校验
hadoop中自定义bean对象步骤:
write
方法和readFields
方法(write方法出现的属性顺序必须和readFields的读取顺序一致)toString
方法,否则存入磁盘的是地址值comparable
接口。mapreduce = map + reduce
mapreduce = inputFormat --> map --> shuffle(排序) --> reduce -->outputFormat
实现类有TextInputFormat和TextOutputFormat, 其中重点是切片逻辑和读写逻辑,读写部分的代码框架已经写死了,主要关注如何切片即可。
数据块:Block是物理上真的分开存储了。
数据切片:只是逻辑上进行分片处理,每个数据切片对应一个MapTask。
正常来说,如果数据有300M,我们按照常理来说会平均划分成3 x 100 M,但是物理上每个物理块是128M,每个MapTask进行计算时需要从另外那个主机读取数据,跨越主机读取数据需要进行网络IO,这是很慢的。
所有MR选择的是按照128M来进行切分,尽管这样会导致划分的数据块并不是十分均匀,但是对于网络IO的延迟来说,还是可以接受的。