从JVM角度看MapReduce运行过程及运行过程中可调优的选项

  1. job提交后,需根据参数启动Mapper、Reducer任务,–那么Map task 的个数怎么设置

    如果Map task过多,即每个任务处理一小部分数据并生成一个中间文件,将引起IO过多,文件过多;
    如果Map task过少,则并行度过低,不能有效利用集群资源,处理时间长;

    影响Map task个数的因素有三个:
    (1)读取的文件个数:默认情况下一个文件起始会启动一个map task
    但是当有许多小文件时,如每个文件5M,单独启动一个task消耗过大
    对于hive可通过设置hive参数将低于128M的小文件合并

set mapred.max.split.size=256000000 // 每个map最大的输入大小
		set mapred.min.split.size.per.node=128000000	//一个节点上split块大小最低限度
	//低于128M的小文件,数据在一个节点会合并,在多个不同的节点会把数据抓过来进行合并。
 设置合并器:
   set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;	
   set hive.merge.mapFiles=true;	//map only任务结束时启动合并
   set hive.merge.mapredFiles=true;	//reduce任务结束时启动合并
   set hive.merge.size.per.task=256000000;	//per task合并文件的大小
(2)读取的文件大小:默认情况下一个map读取文件大小为splitSize;当某个文件大小超过splitSize时,会启动多个task;splitSize参数如下:
mapreduce.input.fileinputformat.split.minsize //启动map最小的split size大小,默认0
mapreduce.input.fileinputformat.split.maxsize //启动map最大的split size大小,默认256M
splitSize = Math.max(minSize, Math.min(maxSize, blockSize));
默认splitSize等于blockSize,即每128M 数据,会启动一个map task;但是如果最后一个文件块小于128*1.1时只会启动一个task;

提交job:
hadoop jar XXXX.jar wordcont -Dmapreduce.input.fileinputformat.split.maxsize=xxx -Dmapreduce.input.fileinputformat.split.minsize=xxx
或者通过api设置
FileInputFormat.setMaxInputSplitSize(job, 20971520l);
FileInputFormat.setMinInputSplitSize(job, 1000);
(3)job参数设置
	见以上默认情况与可调整参数;
  1. Map任务结束后根据key对数据进行partition,返回partition值
    partition数据有一些几点需注意:
    1)数据是否需要全局有序,默认情况下partition值是对key的hash值除以reduce个数;并对一个partition内的数据进行排序;如果要确保数据全局有序,有两种方法,一是设定只有一个reduce任务,但是这种方式对性能影响过大;二是对重写partition类,确保各个partition之间的数据是有序的,例如第一个partition的key范围为1-5,第二个为6-10;

2)数据倾斜:由于数据分布不均匀引起partition后数据不均衡,某一些partition数据过多,有些过少
3)key值为对象类型,包含多个成员变量,比如field1、field2,需要对field1排序后,对field2进行二次排序;

默认的partition中getPartition方法:

public class HashPartitioner<K, V> extends Partitioner<K, V> {

/** Use {@link Object#hashCode()} to partition. */
public int getPartition(K key, V value,
						int numReduceTasks) {
	return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}

重写partition类:

public class ProvincePartitioner extends Partitioner<Text, FlowBean>{

	@Override
	public int getPartition(Text key, FlowBean value, int numPartitions) {
		
		
		return 你的partition逻辑;
	}

}

在main方法指定maptask数据分区逻辑类,默认使用HashPartitioner

job.setPartitionerClass(ProvincePartitioner.class);
  1. partition数据输出到环形缓冲区,溢写到磁盘
    环形缓冲区为一个叫Kvbuffer的字节数组,value和索引两部分,索引为4元组:value的起始位置、key的起始位置、partition值、value的长度;默认buffer大小为100M,当达到80%buffer大小时开始溢写;当数据溢写到磁盘后,将形成一个个小文件,可设置小文件一次性合并的个数,默认为10个;
    同时可设置对map输出进行压缩,以减少磁盘IO;
//buffer大小设置
	mapreduce.task.io.sort.mb=100
	mapreduce.map.sort.spill.percent=0.8 
	mapreduce.task.io.sort.factor=10
mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.DefaultCodec //压缩方式
mapreduce.map.output.compress=false //对map输出进行压缩
		
  1. 溢写过程进行根据partition和key进行sort排序

  2. reduce拉取map输出

一个map任务完成后回想ApplicationMaster报告,同时reduce任务会不断地向ApplicationMaster询问任务完成情况,一旦某个map任务完成达到一定比例(5%),reduce任务将到map机器copy需要的数据;map数据不会立刻删除,而是等到所有任务结束后再删除,为了防止重跑;
那么reduce到map拉取数据如果一次拉取一个还是同时启动多个线程去拉取呢?默认为5个,如果同时又100个map任务完成一个reduce同时只拉取5个,可调大这个值:

mapreduce.reduce.shuffle.parallelcopie=5 //设置拉取数据个数
mapreduce.reduce.shuffle.read.timeout=18000 //设置拉取数据超时时间
  1. reduce合并拉取的数据
    reduce端对于拉取的数据有一个合并过程,同时也需要存储map数据,如果内存不够将溢写到磁盘,那么可
    (1)调整内存大小默认是(0.7) 倍JVM堆内存
    (2)调整溢写到磁盘的时堆内存占用比例
    (3)溢写到磁盘过程中数据的合并:内存中合并后存入内存、内存中合并后存入磁盘、磁盘到磁盘的合并
mapreduce.reduce.shuffle.input.buffer.percent=0.7
mapreduce.reduce.shuffle.merge.percent=0.66 
mapreduce.reduce.merge.memtomem.enabled=false //内存到内存合并
  1. 用户自定义reduce函数调用

    默认情况下,是将所有shuffle后的数据都存入磁盘后,再启动reduce函数,即reduce数据全部都是由磁盘读取,可设置将reduce数据一部分存入内存,提高读取速度;

mapreduce.reduce.input.buffer.percent=0.0	//缓存比例,默认0
set mapreduce.job.reduces=<number>  //hive设置reduce作业个数
set hive.exec.reducers.max=<number> //最大reduce个数,默认1009
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值