1

次の形式で複数の異なるキーが生成されています。

「7112」、「69 2 3」、「6856」など。

しかし、私はこれらのペアのほとんどが同じレデューサーに行くことがわかりました。

カスタムパーティショナーを実装した場合でも、hash_val%numReducersを使用するgetNumPartitionerメソッドは、ほとんどの場合、値を返します。この値は、ロードする少数のレデューサーにグループ化されますが、他のレデューサーは空のままです。、私の理解によれば、WritableComparatorを使用してキーを並べ替えることはできますが、キーを制御して別のレデューサーに移動することはできません。

負荷分散を改善する方法はありますか?plsは役立ちます。

説明を明確にするために、以下にいくつかのコードを添付しています。

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

ご覧のとおり、異なるキーは同じレデューサーにマップされる傾向があります。

助けてください!ありがとう!

4

3 に答える 3

1

データスキューの問題があるようです。パーティショナーをもう少し賢くする必要があります。あなたが試すことができるいくつかのこと:

  • HadoopにはMurmurHash実装が付属しています。パーティショナーでhashCode()の代わりに使用してみると、パーティションがより均等になる可能性があります。
  • 多分あなたはハッシュを超えて見る必要があります。キーがどのように生成されるかについて、より均等に配布するために利用できるものはありますか?たとえば、キー「71 1 2」でスペースを分割し、最初の番号(たとえば71)をパーティションの数で変更できますか?

データ内の一部のキーが実際に重複しているかどうかについては言及していません。もしそうなら、カスタムコンバイナーが役立つかもしれません。

于 2012-07-21T11:59:16.793 に答える
1

まず、ハッシュコードが負の場合があり、負のパーティションと呼ばれるものがないため、Javaのモジュラス演算を単純に実行することはできません。したがって、おそらく絶対値を取るかもしれません。

次に、インターネットで見つけた強力なハッシュ関数です。通常の32ビット整数の代わりに、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 に答える
0

処理したデータの性質が原因で分散が不均衡になる可能性があるため、「より良い」ハッシュ関数を使用することが役立つかどうかはわかりません。同じ入力に対して、ハッシュ関数は常に同じ出力を提供します。

于 2015-08-27T21:14:38.723 に答える