hadoop排序 -- 全排序
程序员文章站
2022-03-14 14:23:33
目录 一、关于Reducer全排序 1.1、 什么叫全排序 1.2、 分区的标准是什么 二、全排序的三种方式 2.1、 一个Reducer 2.2、 自定义分区函数 2.3、 采样 一、关于Reducer全排序 1.1、什么叫全排序? 在所有的分区(Reducer)中,KEY都是有序的: 正确举例: ......
目录
一、关于Reducer全排序
1.1、 什么叫全排序
1.2、 分区的标准是什么
二、全排序的三种方式
2.1、 一个Reducer
2.2、 自定义分区函数
2.3、 采样
一、关于Reducer全排序
1.1、什么叫全排序?
在所有的分区(Reducer)中,KEY都是有序的:
- 正确举例:如Reducer分区1中的key是1、3、4,分区2中的key是5、8、9
- 错误举例:如Reducer分区1中的key是1、3、4,分区2中的key是2、7、9
1.2、数据分区的标准是什么?
默认的分区方式是根据mapper后的key的hash值,除以Reducer的分区数量,取其余数判定;例:
- 某key的hash值是999,此时有3个分区(Reducer),则999 % 3 = 0;则该key和其对应value会分在第一个区(同理,当余数为1,2时会分在对应的另外两个区)。
注意:若key的类型是Text类(或IntWritable等)的,则计算的是Text类型的key的hash值,而非通过Text获取到的String(或int等)类型的hash值。
也可自定义分区的判定方式,见下2.2、自定义分区函数
二、全排序的三种方式
- 一个Reduce
- 自定义分区函数
- 采样
2.1、一个Reduce
只有一个Reduce分区,自然是全排序效果
2.2、自定义分区函数
- 创建一个继承Partitioner的类,如:Partition
- 重写其”getPartition“方法,作为判断分区的依据
- 在main的job中将其加入:job.setPartitionerClass(Partition.class);
以随机分区为例,伪代码如下:
1 public class Partition extends Partitioner <Text,IntWritable>{ 2 3 @Override 4 public int getPartition(Text text, IntWritable intWritable, int numPartitions) { 5 Random r = new Random(); 6 //根据分区的数量(numPartitions),获取一个随机值返回,返回的值作为Key判断分区的依据 7 int i = r.nextInt(numPartitions); 8 return i; 9 } 10 } 11 12 public class RandomAPP { 13 public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { 14 ...... 15 16 //放判断放入分区的方式(随机放入) 17 job.setPartitionerClass(Partition.class); 18 19 ...... 20 21 //等待执行MapperReducer 22 job.waitForCompletion(true); 23 } 24 }
2.3、采样:TotalOrderPartition
- RandomSampler:随机采样 ,性能差,适合乱序数据
- IntervalSampler:间隔采样 ,性能较好,适合有序数据
- SplitSampler:切片采样 ,性能较好,适合有序数据
以随机采样为例,伪代码如下:
注:以下需要放在App中设置配置文件的后面
1 //在App中指定分区函数类 2 job.setPartitionerClass(TotalOrderPartition.class); 3 4 //设置文件的写入路径 5 TotalOrderPartition.setPartitionFile(job.getConfiguration(),new Path("E:/par.dat")); 6 7 /** 8 * 初始化采样器 9 * RandomSampler 采用随机采样的方式 10 * freq 每个Key被选中的概率 freq x key > 分区数 11 * numSamples 需要的样本数 numSamples > 分区数 12 * maxSplitsSampled 文件最大切片数 maxSplitsSampled > 当前切片数 13 */ 14 InputSampler.RandomSampler = new InputSampler.RandomSampler(freq, numsamples,maxsplitsSampled ); 15 16 //写入采样数据 17 InputSampler.writePartitionFile(job,sampler);
Over