[MapReduce_add_3] MapReduce 通过分区解决数据倾斜
0. 说明
数据倾斜及解决方法的介绍与代码实现
1. 介绍
【1.1 数据倾斜的含义】
大量数据发送到同一个节点进行处理,造成此节点繁忙甚至瘫痪,而其他节点资源空闲
【1.2 解决数据倾斜的方式】
重新设计 Key(配合二次 MR 使用)

随机分区
伪代码如下:
RandomPartition extends Partitioner{
return r.nextInt()
}
2. 重新设计 Key 代码编写
[2.1 WCMapper.java]
package hadoop.mr.dataskew; 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 java.io.IOException;
import java.util.Random; /**
* Mapper 程序
* 重新设计 Key
*/
public class WCMapper extends Mapper<LongWritable, Text, Text, IntWritable> { Random r = new Random();
int i; @Override
protected void setup(Context context) throws IOException, InterruptedException {
// 获取 reduce 的个数
i = context.getNumReduceTasks();
} /**
* map 函数,被调用过程是通过 while 循环每行调用一次
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 将 value 变为 String 格式
String line = value.toString();
// 将一行文本进行截串
String[] arr = line.split(" "); for (String word : arr) { String newWord = word + "_" + r.nextInt(i); context.write(new Text(newWord), new IntWritable(1));
} }
}
[2.2 WCReducer.java]
package hadoop.mr.dataskew; import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; /**
* Reducer 类
*/
public class WCReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
/**
* 通过迭代所有的 key 进行聚合
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0; for (IntWritable value : values) {
sum += value.get();
} context.write(key,new IntWritable(sum));
}
}
[2.3 WCMapper2.java]
package hadoop.mr.dataskew; 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 java.io.IOException; /**
* Mapper 程序2
* 重新设计 Key
*/
public class WCMapper2 extends Mapper<LongWritable, Text, Text, IntWritable> {
/**
* map 函数,被调用过程是通过 while 循环每行调用一次
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 将 value 变为 String 格式
String line = value.toString();
// 切割一行文本分为 key 和 value
String[] arr = line.split("\t"); String word = arr[0]; Integer count = Integer.parseInt(arr[1]); // 重新设计 Key
String newWord = word.split("_")[0]; context.write(new Text(newWord), new IntWritable(count)); }
}
[2.4 WCReducer2.java]
package hadoop.mr.dataskew; import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; /**
* Reducer 类2
*/
public class WCReducer2 extends Reducer<Text, IntWritable, Text, IntWritable> {
/**
* 通过迭代所有的 key 进行聚合
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0; for (IntWritable value : values) {
sum += value.get();
} context.write(key,new IntWritable(sum));
}
}
[2.5 WCApp.java]
package hadoop.mr.dataskew; 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 WCApp {
public static void main(String[] args) throws Exception {
// 初始化配置文件
Configuration conf = new Configuration(); // 仅在本地开发时使用
conf.set("fs.defaultFS", "file:///"); // 初始化文件系统
FileSystem fs = FileSystem.get(conf); // 通过配置文件初始化 job
Job job = Job.getInstance(conf); // 设置 job 名称
job.setJobName("data skew"); // job 入口函数类
job.setJarByClass(WCApp.class); // 设置 mapper 类
job.setMapperClass(WCMapper.class); // 设置 reducer 类
job.setReducerClass(WCReducer.class); // 设置分区数量
job.setNumReduceTasks(3); // 设置 map 的输出 K-V 类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class); // 设置 reduce 的输出 K-V 类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class); // 设置输入路径和输出路径
Path pin = new Path("E:/test/wc/dataskew.txt");
Path pout = new Path("E:/test/wc/out");
// Path pin = new Path(args[0]);
// Path pout = new Path(args[1]);
FileInputFormat.addInputPath(job, pin);
FileOutputFormat.setOutputPath(job, pout); // 判断输出路径是否已经存在,若存在则删除
if (fs.exists(pout)) {
fs.delete(pout, true);
} // 执行 job
boolean b = job.waitForCompletion(true); if (b) {
// 通过配置文件初始化 job
Job job2 = Job.getInstance(conf); // 设置 job 名称
job2.setJobName("data skew2"); // job 入口函数类
job2.setJarByClass(WCApp.class); // 设置 mapper 类
job2.setMapperClass(WCMapper2.class); // 设置 reducer 类
job2.setReducerClass(WCReducer2.class); // 设置分区数量
// job2.setNumReduceTasks(3); // 设置 map 的输出 K-V 类型
job2.setMapOutputKeyClass(Text.class);
job2.setMapOutputValueClass(IntWritable.class); // 设置 reduce 的输出 K-V 类型
job2.setOutputKeyClass(Text.class);
job2.setOutputValueClass(IntWritable.class); // 设置输入路径和输出路径
Path pin2 = new Path("E:/test/wc/out");
Path pout2 = new Path("E:/test/wc/out2");
// Path pin = new Path(args[0]);
// Path pout = new Path(args[1]);
FileInputFormat.addInputPath(job2, pin2);
FileOutputFormat.setOutputPath(job2, pout2); // 判断输出路径是否已经存在,若存在则删除
if (fs.exists(pout2)) {
fs.delete(pout2, true);
} // 执行 job
job2.waitForCompletion(true);
}
}
}
3. 随机分区代码编写
[3.1 WCMapper.java]
package hadoop.mr.dataskew2; 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 java.io.IOException; /**
* Mapper 程序
* 重新设计 Key
*/
public class WCMapper extends Mapper<LongWritable, Text, Text, IntWritable> { /**
* map 函数,被调用过程是通过 while 循环每行调用一次
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 将 value 变为 String 格式
String line = value.toString(); // 将一行文本进行截串
String[] arr = line.split(" "); for (String word : arr) {
context.write(new Text(word), new IntWritable(1));
} }
}
[3.2 WCReducer.java]
package hadoop.mr.dataskew2; import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; /**
* Reducer 类
*/
public class WCReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
/**
* 通过迭代所有的 key 进行聚合
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0; for (IntWritable value : values) {
sum += value.get();
} context.write(key, new IntWritable(sum));
}
}
[3.3 WCMapper2.java]
package hadoop.mr.dataskew2; 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 java.io.IOException; /**
* Mapper 程序2
* 重新设计 Key
*/
public class WCMapper2 extends Mapper<LongWritable, Text, Text, IntWritable> {
/**
* map 函数,被调用过程是通过 while 循环每行调用一次
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 将 value 变为 String 格式
String line = value.toString();
// 切割一行文本分为 key 和 value
String[] arr = line.split("\t"); String word = arr[0]; Integer count = Integer.parseInt(arr[1]); context.write(new Text(word), new IntWritable(count)); }
}
[3.4 RandomPartitioner.java]
package hadoop.mr.dataskew2; import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner; import java.util.Random; /**
* 随机分区类
*/
public class RandomPartitioner extends Partitioner<Text, IntWritable> { Random r = new Random(); @Override
public int getPartition(Text text, IntWritable intWritable, int numPartitions) {
return r.nextInt(numPartitions);
}
}
[3.5 WCApp.java]
package hadoop.mr.dataskew2; 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 WCApp {
public static void main(String[] args) throws Exception {
// 初始化配置文件
Configuration conf = new Configuration(); // 仅在本地开发时使用
conf.set("fs.defaultFS", "file:///"); // 初始化文件系统
FileSystem fs = FileSystem.get(conf); // 通过配置文件初始化 job
Job job = Job.getInstance(conf); // 设置 job 名称
job.setJobName("data skew"); // job 入口函数类
job.setJarByClass(WCApp.class); // 设置 mapper 类
job.setMapperClass(WCMapper.class); // 设置 reducer 类
job.setReducerClass(WCReducer.class); // 设置 partition 类
job.setPartitionerClass(RandomPartitioner.class); // 设置分区数量
job.setNumReduceTasks(3); // 设置 map 的输出 K-V 类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class); // 设置 reduce 的输出 K-V 类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class); // 设置输入路径和输出路径
Path pin = new Path("E:/test/wc/dataskew.txt");
Path pout = new Path("E:/test/wc/out");
// Path pin = new Path(args[0]);
// Path pout = new Path(args[1]);
FileInputFormat.addInputPath(job, pin);
FileOutputFormat.setOutputPath(job, pout); // 判断输出路径是否已经存在,若存在则删除
if (fs.exists(pout)) {
fs.delete(pout, true);
} // 执行 job
boolean b = job.waitForCompletion(true); if (b) {
// 通过配置文件初始化 job
Job job2 = Job.getInstance(conf); // 设置 job 名称
job2.setJobName("data skew2"); // job 入口函数类
job2.setJarByClass(hadoop.mr.dataskew.WCApp.class); // 设置 mapper 类
job2.setMapperClass(WCMapper2.class); // 设置 reducer 类
job2.setReducerClass(WCReducer.class); // 设置分区数量
// job2.setNumReduceTasks(3); // 设置 map 的输出 K-V 类型
job2.setMapOutputKeyClass(Text.class);
job2.setMapOutputValueClass(IntWritable.class); // 设置 reduce 的输出 K-V 类型
job2.setOutputKeyClass(Text.class);
job2.setOutputValueClass(IntWritable.class); // 设置输入路径和输出路径
Path pin2 = new Path("E:/test/wc/out");
Path pout2 = new Path("E:/test/wc/out2");
// Path pin = new Path(args[0]);
// Path pout = new Path(args[1]);
FileInputFormat.addInputPath(job2, pin2);
FileOutputFormat.setOutputPath(job2, pout2); // 判断输出路径是否已经存在,若存在则删除
if (fs.exists(pout2)) {
fs.delete(pout2, true);
} // 执行 job
job2.waitForCompletion(true);
} }
}
[MapReduce_add_3] MapReduce 通过分区解决数据倾斜的更多相关文章
- Hadoop_22_MapReduce map端join实现方式解决数据倾斜(DistributedCache)
1.Map端Join解决数据倾斜 1.Mapreduce中会将map输出的kv对,按照相同key分组(调用getPartition),然后分发给不同的reducetask 2.Map输出结果的时候 ...
- Spark性能调优之解决数据倾斜
Spark性能调优之解决数据倾斜 数据倾斜七种解决方案 shuffle的过程最容易引起数据倾斜 1.使用Hive ETL预处理数据 • 方案适用场景:如果导致数据倾斜的是Hive表.如果该Hiv ...
- MapReduce如何解决数据倾斜?
数据倾斜是日常大数据查询中隐形的一个BUG,遇不到它时你觉得数据倾斜也就是书本博客上的一个无病呻吟的偶然案例,但当你遇到它是你就会懊悔当初怎么不多了解一下这个赫赫有名的事故. https://www. ...
- 【Spark篇】---Spark解决数据倾斜问题
一.前述 数据倾斜问题是大数据中的头号问题,所以解决数据清洗尤为重要,本文只针对几个常见的应用场景做些分析 . 二.具体方法 1.使用Hive ETL预处理数据 方案适用场景: 如果导致数据倾斜的是 ...
- 专访周金可:我们更倾向于Greenplum来解决数据倾斜的问题
周金可,就职于听云,维护MySQL和GreenPlum的正常运行,以及调研适合听云业务场景的数据库技术方案. 听云周金可 9月24日,周金可将参加在北京举办的线下活动,并做主题为<GreenPl ...
- MapReduce分区数据倾斜
什么是数据倾斜? 数据不可避免的出现离群值,并导致数据倾斜,数据倾斜会显著的拖慢MR的执行速度 常见数据倾斜有以下几类 1.数据频率倾斜 某一个区域的数据量要远远大于其他区域 2.数据大小倾斜 ...
- Hadoop基础-MapReduce的数据倾斜解决方案
Hadoop基础-MapReduce的数据倾斜解决方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据倾斜简介 1>.什么是数据倾斜 答:大量数据涌入到某一节点,导致 ...
- Spark性能优化之道——解决Spark数据倾斜(Data Skew)的N种姿势
原创文章,同步首发自作者个人博客转载请务必在文章开头处注明出处. 摘要 本文结合实例详细阐明了Spark数据倾斜的几种场景以及对应的解决方案,包括避免数据源倾斜,调整并行度,使用自定义Partitio ...
- 实战 | Hive 数据倾斜问题定位排查及解决
Hive 数据倾斜怎么发现,怎么定位,怎么解决 多数介绍数据倾斜的文章都是以大篇幅的理论为主,并没有给出具体的数据倾斜案例.当工作中遇到了倾斜问题,这些理论很难直接应用,导致我们面对倾斜时还是不知所措 ...
随机推荐
- Android Studio 快捷键总结(OS X)
Action shortcut key 解释 跳转到类 cmd+0 跳转到文件 cmd+shift+0 跳转到函数 cmd+alt+0 最近打开的文件 cmd+e 最近编辑的文件 ...
- Runtime 自动化归档
Runtime的使用 (id)initWithCoder:(NSCoder *)decoder { if (self = [super init]) { unsigned ; Ivar *ivars ...
- OkHttp3 任务队列
OkHttp3 有两种运行方式: 1.同步阻塞调用并且直接返回: 2.通过内部线程池分发调度实现非阻塞的异步回调; 下面讲的是非阻塞异步回调,OkHttp在多并发网络下的分发调度过程,主要是Dispa ...
- Spring Boot + Spring Cloud 实现权限管理系统 后端篇(十八):注册中心(Spring Cloud Consul)
什么是 Consul Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与 ...
- 利用python数据分析与挖掘相关资料总结
小生今年研二,目前主要从事软件工程数据挖掘与分析.之前一直苦于找不到一个从数据预处理.数据分析.数据可视化和软件建模的统一平台.因此,小生辗转反辙学习了java,R语言,python,scala等等. ...
- 自动化运维(1)之二进制部署MySQL5.7
二进制部署MySQL5.7 这个文档用于基础解释,后面通过ansible的自动化对MySQL单实例进行安装部署. 1.解压文件 # tar zxvf mysql-5.7.22-linux-glibc2 ...
- 可能会导致循环或多重级联路径。请指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
错误提示:可能会导致循环或多重级联路径.请指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束. 原因:自表连接(同一张表 ...
- C# 基础运算符及运算
本节主要讲述运算符的分类及其实际运用 运算符 分类 符号 解释 优先级 算数 ++ -- 加加(加1) 减减(减1) 由高到低,即执行顺序由上到下(圆括号的优先级最高) * / % 乘 除 ...
- C#常用单元测试框架比较:XUnit、NUnit和Visual Studio(MSTest)
做过单元测试的同学大概都知道以上几种测试框架,但我一直很好奇它们到底有什么不同,然后搜到了一篇不错的文章清楚地解释了这几种框架的最大不同之处. 地址在这里:http://www.tuicool.com ...
- Java学习笔记之——类与对象
1.参数的传递方式 1)值传递 2)引用传递 2.类和对象: (1)类的定义: public class 类名{ 类型 属性1: 类型 属性2: ……… public 返回值类型 方法名1(形参){ ...