1

我以以下格式生成了多个不同的密钥:

“71 1 2”、“69 2 3”、“68 5 6”等

但是,我发现这些对中的大多数都使用相同的减速器。

即使我实现了一个自定义分区器,我们使用的 getNumPartitioner 方法,hash_val % numReducers,也主要返回值,该值由少数几个加载它们的减速器组成,而其他减速器保持空闲。,据我了解,我们可以使用 WritableComparator 对keys进行排序但不能控制keys去不同的reducer。

有没有办法改善负载平衡?请帮忙。

我在下面附上一些代码以使我的解释清楚:

String a = "71 1 2";
String b = "72 1 1";
String c = "70 1 3";

int hash_a = a.hashCode();
int hash_b = b.hashCode();
int hash_c = c.hashCode();

int part_a = hash_a % 10;
int part_b = hash_b % 10;
int part_c = hash_c % 10;

System.out.println("hash a: "+hash_a+" part_a: "+part_a);
System.out.println("hash b: "+hash_b+" part_b: "+part_b);
System.out.println("hash c: "+hash_c+" part_c: "+part_c);

输出:

哈希 a:1620857277 part_a:7 哈希 b:1621780797 part_b:7 哈希 c:1619933757 part_c:7

正如我们所见,不同的键倾向于映射到同一个 reducer。

请帮忙!谢谢!

4

3 回答 3

1

首先,您不能简单地采用 java 模运算,因为有时哈希码可能是负数,并且肯定不存在所谓的负分区。所以你可能会取一个绝对值。

其次是我在互联网上找到的一个强大的哈希函数。它不是正常的 32 位 int,而是生成 64 位长。同样,这也受到负分区问题的影响,但您可以自己纠正它。

private static long[] byteTable;
private static final long HSTART = 0xBB40E64DA205B064L;
private static final long HMULT = 7664345821815920749L;

private static long[] createLookupTable() {
byteTable = new long[256];
long h = 0x544B2FBACAAF1684L;
for (int i = 0; i < 256; i++) {
  for (int j = 0; j < 31; j++) {
    h = (h >>> 7) ^ h;
    h = (h << 11) ^ h;
    h = (h >>> 10) ^ h;
  }
  byteTable[i] = h;
}
return byteTable;
}
public static long hash(String s) {
byte[] data = s.getBytes();
long h = HSTART;
final long hmult = HMULT;
final long[] ht = createLookupTable();
for (int len = data.length, i = 0; i < len; i++) {
  h = (h * hmult) ^ ht[data[i] & 0xff];
}
return h;
} 

public static void main(String[] args) {

String a = "71 1 2";
String b = "72 1 1";
String c = "70 1 3";

long hash_a = hash(a);
long hash_b = hash(b);
long hash_c = hash(c);

long part_a = hash_a % 10;
long part_b = hash_b % 10;
long part_c = hash_c % 10;

System.out.println("hash a: "+hash_a+" part_a: "+part_a);
System.out.println("hash b: "+hash_b+" part_b: "+part_b);
System.out.println("hash c: "+hash_c+" part_c: "+part_c);
}
于 2012-07-21T07:07:10.013 回答
1

看起来你有一个数据倾斜问题,你需要在你的分区器中更聪明一点。您可以尝试几件事:

  • Hadoop 附带了一个MurmurHash实现。您可以尝试在分区程序中使用它代替 hashCode() ,也许这会让您获得更均匀的分区。
  • 也许您需要超越散列。是否有任何关于您的密钥是如何生成的,您可以利用它来获得更均匀的分布?例如,在键“71 1 2”上,您可以按分区数分割空间并修改第一个数字(例如 71)吗?

您没有提到数据中的某些键是否实际上是重复的。如果是这样,自定义组合器可能会有所帮助。

于 2012-07-21T11:59:16.793 回答
0

我不确定使用“更好”的哈希函数是否会有所帮助,因为不平衡的分布可能是由于您处理的数据的性质。对于相同的输入,哈希函数总是给出相同的输出。

于 2015-08-27T21:14:38.723 回答