Hadoop_22_MapReduce map端join实现方式解决数据倾斜(DistributedCache)
1.Map端Join解决数据倾斜
1.Mapreduce中会将map输出的kv对,按照相同key分组(调用getPartition),然后分发给不同的reducetask
2.Map输出结果的时候调用了Partitioner组件(返回分区号),由它决定将数据放到哪个区中,默认的分组规
则为:根据key的hashcode%reducetask数来分发,源代码如下:
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;
}
}
3.所以:如果要按照我们自己的需求进行分组,则需要改写数据分发(分组)组件Partitioner,自定义一个
CustomPartitioner继承抽象类:Partitioner,来返回一个分区编号
4.然后在job对象中,设置自定义partitioner: job.setPartitionerClass(CustomPartitioner.class)
5.自定义partition后,要根据自定义partitioner的逻辑设置相应数量的ReduceTask
存在的问题:如若Mapper输出的一些Key特别多,另一些Key特别少就会产生数据倾斜,造成一些Reducer特别忙
,一些则比较闲,我们说Mapper端相同key的输出数据会发到同一个Redurce端,需要把key相同的放在一起才能进行
拼接,所以才需要Reducer。如果我们不需要Reducer就能做拼接,就不存在数据倾斜了。
解决方案:Map端Join解决数据倾斜,我们为每一个MapTask准备一个表的全表。这种机制叫做Map Side Join。
当然这个表的全表不能很大
2.map端join算法实现原理:
原理阐述:1.适用于关联表中有小表的情形;2.可以将小表分发到所有的map节点,这样,map节点就可以在本地
对自己所读到的大表数据进行join并输出最终结果,可以大大提高join操作的并发度,加快处理速度;3.Hadoop提供
了一个Distributed Cache机制,能把文件在合适的时候发给MapTask,MapTask就可以从本地进行加载小表数据;
3.map端join代码实现示例:
:先在mapper类中预先定义好小表,进行join
:并用distributedcache机制将小表的数据分发到每一个maptask执行节点,从而每一个maptask节点可以从本地加
载到小表的数据,进而在本地即可实现join
:引入实际场景中的解决方案:一次加载数据库或者用distributedcache
代码:
package cn.gigdata.hdfs.mr;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; /**
* 解决在Redue端的数据倾斜问题
* @author Administrator
*/ public class MapSideJoin {
public static class MapSideJoinMapper extends Mapper<LongWritable, Text, Text, NullWritable>{ // 用一个hashmap来加载保存产品信息表
Map<String, String> pdInfoMap = new HashMap<String, String>();
Text k = new Text();
/**
* 通过阅读父类Mapper的源码,发现 setup方法是在maptask处理数据之前调用一次 可以用来做一些初始化工作
*/
@Override
protected void setup(Mapper<LongWritable, Text, Text, NullWritable>.Context context) throws IOException, InterruptedException {
//读取MapTask工作目录(已经存在,直接根据文件名进行读取)的文件,将数据放入HashMap中
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("pdts.txt")));
String line;
while(StringUtils.isNotEmpty(line = br.readLine())){
String[] fields = line.split(",");
pdInfoMap.put(fields[0], fields[1]);
}
br.close();
} //由于已经持有完整的产品信息表,所以在map方法中就能实现join逻辑了
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String orderLine = value.toString();
String fields[] = orderLine.split(",");
//根据订单ID,在商品表中get到ID对应的商品名称
String pdName = pdInfoMap.get(fields[2]);
k.set(orderLine + "," + pdName);
context.write(k, NullWritable.get());
}
} public static void main(String[] args) throws Exception {
Configuration conf = new Configuration(); Job job = Job.getInstance(conf); job.setJarByClass(MapSideJoin.class); job.setMapperClass(MapSideJoinMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class); FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1])); // 指定需要缓存一个文件到所有的maptask运行节点工作目录
/* job.addArchiveToClassPath(archive); */// 缓存jar包到task运行节点的classpath中
/* job.addFileToClassPath(file); */// 缓存普通文件到task运行节点的classpath中
/* job.addCacheArchive(uri); */// 缓存压缩包文件到task运行节点的工作目录
/* job.addCacheFile(uri) */// 缓存普通文件到task运行节点的工作目录 // 将产品表文件缓存到Maptask工作节点的工作目录中去(Map运行时将会得到改文件)
job.addCacheFile(new URI("file:/F:/pduct/pdts.txt")); //map端join的逻辑不需要reduce阶段,设置reducetask数量为0
job.setNumReduceTasks(0); boolean res = job.waitForCompletion(true);
System.exit(res ? 0 : 1);
}
}
产品数据文件:pdts.txt
P0001,sss,1001,2
P0002,111,1000,3
P0003,www,1002,4
订单数据文件:order.txt
1001,20150710,P0001,2
1002,20150710,P0001,3
1002,20150710,P0002,3
1003,20150710,P0003,3
运行结果文件:part-m-00000
1001,20150710,P0001,2,sss
1002,20150710,P0001,3,sss
1002,20150710,P0002,3,111
1003,20150710,P0003,3,www
Hadoop_22_MapReduce map端join实现方式解决数据倾斜(DistributedCache)的更多相关文章
- hadoop的压缩解压缩,reduce端join,map端join
hadoop的压缩解压缩 hadoop对于常见的几种压缩算法对于我们的mapreduce都是内置支持,不需要我们关心.经过map之后,数据会产生输出经过shuffle,这个时候的shuffle过程特别 ...
- Spark性能调优之解决数据倾斜
Spark性能调优之解决数据倾斜 数据倾斜七种解决方案 shuffle的过程最容易引起数据倾斜 1.使用Hive ETL预处理数据 • 方案适用场景:如果导致数据倾斜的是Hive表.如果该Hiv ...
- 【Spark篇】---Spark解决数据倾斜问题
一.前述 数据倾斜问题是大数据中的头号问题,所以解决数据清洗尤为重要,本文只针对几个常见的应用场景做些分析 . 二.具体方法 1.使用Hive ETL预处理数据 方案适用场景: 如果导致数据倾斜的是 ...
- [MapReduce_add_3] MapReduce 通过分区解决数据倾斜
0. 说明 数据倾斜及解决方法的介绍与代码实现 1. 介绍 [1.1 数据倾斜的含义] 大量数据发送到同一个节点进行处理,造成此节点繁忙甚至瘫痪,而其他节点资源空闲 [1.2 解决数据倾斜的方式] 重 ...
- map端join
package my.hadoop.hdfs.mapreduceJoin; import java.io.BufferedReader; import java.io.FileInputStream; ...
- 专访周金可:我们更倾向于Greenplum来解决数据倾斜的问题
周金可,就职于听云,维护MySQL和GreenPlum的正常运行,以及调研适合听云业务场景的数据库技术方案. 听云周金可 9月24日,周金可将参加在北京举办的线下活动,并做主题为<GreenPl ...
- MapReduce如何解决数据倾斜?
数据倾斜是日常大数据查询中隐形的一个BUG,遇不到它时你觉得数据倾斜也就是书本博客上的一个无病呻吟的偶然案例,但当你遇到它是你就会懊悔当初怎么不多了解一下这个赫赫有名的事故. https://www. ...
- Spark性能优化之道——解决Spark数据倾斜(Data Skew)的N种姿势
原创文章,同步首发自作者个人博客转载请务必在文章开头处注明出处. 摘要 本文结合实例详细阐明了Spark数据倾斜的几种场景以及对应的解决方案,包括避免数据源倾斜,调整并行度,使用自定义Partitio ...
- 061 hive中的三种join与数据倾斜
一:hive中的三种join 1.map join 应用场景:小表join大表 一:设置mapjoin的方式: )如果有一张表是小表,小表将自动执行map join. 默认是true. <pro ...
随机推荐
- swift 第七课 xib 约束的优先级
前期要实现 一个自适应的label 的时候,就知到xib 约束是有优先级的,一直为深入研究: 乘写这个 博客的机会 ,试验下xib 约束的等级 …… 抱歉要查资料,在重新实践,先把主要浏览的网页 连接 ...
- Flutter Window环境运行(VSCode + 单独运行Android 虚拟机)
官网以及很多网上文章的开发都是基于Android ,因为它能创建不同类型移动设备虚拟机.但个人始终觉得它太庞大,启动慢耗资源,但我们使用Flutter又离不开虚拟机. 经过实践,现在能成功的单独启动移 ...
- Jmeter 逻辑控制器 之 Runtime Controller
一.认识 Runtime Controller 控制其下样例执行的时间长度. 设置界面: Runtime (seconds):运行时间,单位秒.即控制其下样例执行多长时间.与线程组中的调度器的持续 ...
- Jmeter 逻辑控制器 之 ForEach 控制器
一.认识 ForEach 控制器 如下,创建一个 ForEach 控制器 设置界面如下: 输入变量前缀:要进行循环读取的变量前缀 Start index for loop (exclusive):循环 ...
- imregionalmax imregionalmin imextendedmax imextendedmin imhmax imhmin 函数的详解 matlab中函数
BW = imregionalmax(I): 该函数获得灰度图像 I 的局部极大值,返回值BW为和原图像大小相同的二值图像,BW中元素1对应极大值,其他元素为0 BW = imregionalmax( ...
- Odoo13 新变化:存货核算
Odoo13将于2019年10月发布,本次发布也包含了大量的改进,例如,对存货核算的重构. 去掉了 产品历史价格product.price.history ,增加了 stock valuation l ...
- BootStrap Table方法使用小结
参考链接:https://www.cnblogs.com/Amaris-Lin/p/7797920.html
- spring security中Authority、Role的区别
最近在研究spring security时,大概研究了一下Authority.Role之间到底有什么本质的区别. 如果你使用的是hasRole方法来判断你的登录用户是否有权限访问某个接口,那么你初始化 ...
- vue中使用第三方插件animate.css实现动画效果
vue中使用第三方插件animate.css实现动画效果1.首先先引入第三方类animated.css2.将你所需要动画的标签用包裹起来3.在transition元素中添加enter-active-c ...
- java-监听器(Listener)
监听器:用于监听web应用中某些对象.信息的创建.销毁等动作,服务器会自动调用相应的方法进行处理.常用于统计在线人数,初始化系统参数等. Javaweb监听器主要监听对象有ServletContext ...