概述:
从所周知,当需求中数据出现分布不均的情况时,按照hadoop mr任务的默认partition方法,会出现某些机子负载过重的情况,这样会拖慢整个任务进度,有时候甚至会宕机。在这里我介绍一个用随机数解决这个问题的方案,下面是通过代码来模拟map根据partition来分区的情况;
原理(追加)
方案就是运用了数学中均匀分布的原理,举个例子:10个小球,有5个盒子,那么每个小球分配到每个盒子的概率都是相同的,即五分之一,那么例子中小球模拟的是mr中的key,盒子模拟的是reducer。这种方案相对于官方提供的用一致性哈希算法有什么优点呢,我们了解到要使用一致性哈希算法达到均匀分布key,哈希算法中的虚拟桶数在足够多,但是hadoop处理的数据都是十亿级数据,key种类也是千万级以上,如果为了更均匀,必然会耗费更多的内存,但是如果采用这种方案,那么几乎是不需要内存来保存key的状态,而且数据量越大,分布就更加均匀
测试代码
package com.mxq.balance;
import java.util.Vector;
public class UNBalanceData {
private Vector<keyAndNum> keyVector=new Vector<keyAndNum>(10);
//这里用于生成不均匀数据样本的信息;
public void intialize(){
keyAndNum kn=new keyAndNum(1,50);
this.keyVector.add(kn);
kn=new keyAndNum(2,100);
this.keyVector.add(kn);
kn=new keyAndNum(3,80);
this.keyVector.add(kn);
//其中keyAndNum(4,1000020)表示key 4 有1000020个记录;
kn=new keyAndNum(4,1000020);
this.keyVector.add(kn);
kn=new keyAndNum(5,10050);
this.keyVector.add(kn);
kn=new keyAndNum(6,200);
this.keyVector.add(kn);
kn=new keyAndNum(7,100050);
this.keyVector.add(kn);
kn=new keyAndNum(8,250);
this.keyVector.add(kn);
kn=new keyAndNum(9,140);
this.keyVector.add(kn);
kn=new keyAndNum(10,90);
this.keyVector.add(kn);
}
//获取总样本数是;
public int getLoop(){
int loop=0;
for(int i=0;i<this.keyVector.size();i++){
loop+=this.keyVector.get(i).getKeyNum();
}
return loop;
}
//根据initialize生成的信息 生成样本时用;
public boolean minus(int key){
for(int i=0;i<this.keyVector.size();i++){
if(this.keyVector.get(i).getKey()==key){
if(this.keyVector.get(i).getKeyNum()<1){
//System.out.println("key :" +key+"'s num "+this.keyVector.get(i).getKeyNum()+ " ,please check program");
return false;
}else{
this.keyVector.get(i).minus();
return true;
}
}
}
return false;
}
}
//此类是模拟reduce
package com.mxq.balance;
import java.util.Vector;
public class reduceContain {
public Vector<keyAndNum> reduceVec=new Vector<keyAndNum>();
//根本key来收集各个key在某个reducer的数量;
public void addKey(int key){
boolean find=false;
int index=-1;
for(int i=0;i<this.reduceVec.size();i++){
if(this.reduceVec.get(i).getKey()==key)
{
find=true;
index=i;
break;
}
}
if(find){
this.reduceVec.get(index).add();
}else
{
keyAndNum kn=new keyAndNum(key,1);
this.reduceVec.add(kn);
}
}
//获取最终key在某个reducer的样本数
public int getResult(int key){
for(int i=0;i<this.reduceVec.size();i++){
if(this.reduceVec.get(i).getKey()==key){
return this.reduceVec.get(i).getKeyNum();
}
}
System.out.println("can not find key");
return 0;
}
}
//保存key的状态或者配置信息;
package com.mxq.balance;
public