MapReduce入门

MapReduce入门

一,MapReduce是什么?

MapReduce是一种分布式的离线计算框架。

它是一种编程的模型,主要用于大型的数据集(大于1TB)的并行计算。将自己的程序运行在分布式系统上,概念是: Map(映射)Reduce(归纳)

指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(规约)函数,用来保证所有映射的键值对中的每一个 共享相同的键组。

应用于大规格的算法图片处理,文字处理

设计理念和思想: 分与合

二,MapReduce的设计理念

2.1 分布式计算

分布式计算将应用分解成很多小的部分,分配给多台计算机节点进行处理。这样可以节约整体计算时间,大大的提高了计算效率。

2.2 移动计算,而不是移动数据

移动计算它的作用是将有用,准确,及时的信息提供给任何时间,任何地点的任何客户

这里我们说的是将计算程序移动到具有数据的集群的计算机节点上进行计算操作。

简称:计算向数据靠拢,减少数据的拉取,加快运行的效率。

三,MapReduce计算框架的组成

在这里插入图片描述

3.1 Mapper详解

Mapper主要的任务就是负责“分”。

简单的说就是把复杂的任务分解为若干个“简单的任务”执行。

对于简单任务,有以下含义:

​ 1.数据或计算规模相比原任务要大大的缩小。

​ 2.就近计算,简单的说就是程序会优先分配到存放了所需数据的节点进行计算。

​ 3.这些小任务可以并行计算,彼此之间是互不干扰的。

在这里插入图片描述

对于Spilt大小的规则:

– max.split 100M

– min.split 10M

– block 64M

对于计算Split的公式:max( min.split , min(max.split,block) )

split实际 = block大小

Map的数目通常是由输入数据的大小决定的,一般就是所有输入文件的总块(block)数.

3.2 Reduce详解

Reduce的任务是对map阶段的结果进行“汇总”并输出

Reduce的数目由mapred-site.xml配置文件里的项目 mapred.reduce.tasks决定。缺省值为1。
在这里插入图片描述

大部分的Reduce任务都是在具有需要数据的节点服务器上运行,这样可以节省通过网络拉取数据的时间,在自己节点,运行效率较高。

但是如果具有数据节点的节点服务器,不支持Reduce任务的执行(资源,cpu,内存等原因),Reduce也是会运行在非数据节点上。

Reduce的数目建议:

​ 0.95/1.75乘(<no. of nodes> mapred.tasktracker.reduce.tasks.maximum)。

用0.95,所有reduce可以在maps一完成时就立刻启动,开始传输map的输出结果。

​ 用1.75,速度快的节点可以在完成第一轮reduce任务后,可以开始第二轮,这样可以得到比较好的负载均衡的效果。

增加reduce的数目会增加整个框架的开销,但可以改善负载均衡,降低由于执行失败带来的负面影响。

3.3 Shuffle

shuffle是在Map和Reduce之间的一个步骤.(其实是属于Reduce的过程,细分的话单独提出也是可以)

​ shuffle的主要作用是可以将mapper的输出按照某种Key值重新切分和组合成n份,把key值符合某种范围的输出送到特定的Reducer那里去处理。

​ 可以简化Reduce的过程。Partitoner: hash(Key) mod(取模) R
在这里插入图片描述

​ map过程中,读取到内存,组成key,value这种数据结构,其中还包括分区信息(Key,Value,P),当达到内存的某个限定值时(内存的百分之80,可以自行设置),发生溢写(内存写入磁盘的操作),一个Map对应一个文件,而P的类型又把文件分成N个部分。

​ shuffle过程中,是发生在各个节点的Map全部完成后,拉取数据后,根据Key值进行聚合操作,按照字典顺序排序(是用快速排序实现),然后将数据发送到reducer运行。


在这里插入图片描述

看以下 WordCount的运行图:
在这里插入图片描述

​ 我们可以看到一个问题,在Mapping后,在同一数据节点上,相同的Key未进行数据的合并,这样shuffing在拉取过程中,可以就会无用的增加了很多拉取的时间(这里针对计数)。完全可以把相同的Key进行合并,然后shuffing在拉取中就加快了数据拉取效率。这个问题我们通常称为 数据倾斜。

​ 对应的解决方案: combiner的作用

​ combiner是在Map和Reduce之间,在Reduce之前,combiner会对Map过程处理的结果进行一次处理,相同Key之间的数据聚合合并。

四,MR架构

一主多从架构

— 主JobTracker:(RM) resourcemanager

负责调度分配每一个子任务task运行于TaskTracker上,如果发现有失败的task就重新分配其任务到其他节点。每一个hadoop集群中只有一个JobTrcker,一般它运行在Master节点上

— 从TaskTracker:(NM) nodemanager

​ TaskTracker主动和JobTracker通信,接收作业,并负责直接执行每一个任务,为了减少网络带宽TaskTracker最好运行在HDFS的DataNode上。

基于上次配置的 HA–Hadoop集群 博客链接: https://blog.csdn.net/weixin_43270493/article/details/85805201

修改配置文件 mapred-site.xml

<configuration>
    <property>
        //mapreduce运行在哪个框架上
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>

修改配置文件 yarn-site.xml

<property>
    //shuffle机制配置
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
</property>
<property>
    //resourcemanager存在单点故障问题,所以给它配置 HA
   <name>yarn.resourcemanager.ha.enabled</name>
   <value>true</value>
 </property>
 <property>
     //RM集群的名字,随意
   <name>yarn.resourcemanager.cluster-id</name>
   <value>mr_wcb</value>
 </property>
 <property>
     //指定RM集群包括哪些节点
   <name>yarn.resourcemanager.ha.rm-ids</name>
   <value>rm1,rm2</value>
 </property>
 <property>
     //指定rm1节点
   <name>yarn.resourcemanager.hostname.rm1</name>
   <value>node02</value>
 </property>
 <property>
     //指定rm2节点
   <name>yarn.resourcemanager.hostname.rm2</name>
   <value>node03</value>
 </property>
 <property>
     //通过zookeeper实现HA
   <name>yarn.resourcemanager.zk-address</name>
   <value>node01:2181,node02:2181,node03:2181</value>
 </property>
4.1 启动流程

启动zookeeper(三台机器)

zkServer.sh  start

启动hdfs集群(任意一个NameNode)

start-dfs.sh 

启动yarn集群(任意一个NameNode)

start-yarn.sh 

在node02,node03上 分别启动resourcemanager

yarn-daemon.sh  start  resourcemanager

五,wordCount代码编写

Mapper.java

package com.mr.wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.hsqldb.lib.StringUtil;

public class WordCountMap extends Mapper<LongWritable, Text, Text, IntWritable> {
	
	@Override
	protected void map(LongWritable key, Text value, Context context)
			throws IOException, InterruptedException {
		//一行文本数据
		String lines = value.toString();
		String [] words = StringUtil.split(lines, " ");
		for (String word: words) {
			context.write(new Text(word), new IntWritable(1));
		}
	}
}

Reduce.java

package com.mr.wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class WordCountReduce extends Reducer<Text, IntWritable, Text,IntWritable>{
	@Override
	protected void reduce(Text key, Iterable<IntWritable> values,
			Context context) throws IOException, InterruptedException {
		int sum =0;
		for (IntWritable count : values) {
			sum = sum + count.get();
		}
		context.write(key, new IntWritable(sum));
	}
}

Job(Runner).java

package com.mr.wordcount;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class Runner {
	
	public static void main(String[] args) throws Exception {
		//配置相关环境
		Configuration conf = new Configuration();
		conf.set("fs.defaultFS", "hdfs://node01:8020");
		conf.set("yarn.resourcemanager.hostname", "node02:8088");
		
		//设置job任务的相关信息
		Job job = Job.getInstance(conf);
		job.setJarByClass(Runner.class);
		job.setJobName("wordcount");
		
		job.setMapperClass(WordCountMap.class);
		job.setReducerClass(WordCountReduce.class);
		
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);
		
		//读取输入文件(读取HDFS上的文件)
		FileInputFormat.addInputPaths(job, "/test/input/wordcount.txt");
		
		//输出结果的路径
		Path path = new Path("/test/output/result");
		FileSystem fs  = FileSystem.get(conf);
		
		if (fs.exists(path)) {
			fs.delete(path, true);
		}
		
		FileOutputFormat.setOutputPath(job, path);
		
		boolean f;
		try {
			f = job.waitForCompletion(true);
			if (f) {
				System.out.println("job success....");
			}else {
				System.out.println("job fail......");
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
}

测试数据:

hello tom
hello jetty  hello myfriend
hello anglebaby
what is hadoop
tomcat and jetty
happy or sad
keep run everyday
belive you are best

输出结果 :

	1
and	1
anglebaby	1
are	1
belive	1
best	1
everyday	1
hadoop	1
happy	1
hello	4
is	1
jetty	2
keep	1
myfriend	1
or	1
run	1
sad	1
tom	1
tomcat	1
what	1
you	1

也可以将项目打成 war包, 上传服务器,命令启动,这里不做介绍,感兴趣的小伙伴可以自行尝试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值