0

2 つのソースからの入力があります。

  1. フォームのマップ出力、

    output.collect(new StockKey(Text(x+" "+id), new Text(id2)), new Text(data));
    
  2. フォームのマップ出力、

    output.collect(new StockKey(new Text(x+" "+id), new Text(1), new Text(data));
    

ジョブ構成:

 conf.setPartitionerClass(CustomPartitioner.class);
 conf.setValueGroupingComparatorClass(StockKeyGroupingComparator.class);

ここで、StockKey は format のカスタム クラスです(new Text(), new Text())

コンストラクタ:

public StockKey(){
    this.symbol = new Text();
    this.timestamp = new Text();
}

グループ化コンパレータ:

public class StockKeyGroupingComparator extends WritableComparator {

    protected StockKeyGroupingComparator() {
        super(StockKey.class, true);
    }  

    public int compare(WritableComparable w1, WritableComparable w2){
        StockKey k1 = (StockKey)w1;
        StockKey k2 = (StockKey)w2;

        Text x1 = new Text(k1.getSymbol());
        Text x2 = new Text(k2.getSymbol());

        return x1.compareTo(x2);

    }

}

しかし、入力からマップ出力値を受け取っていません

マップ出力値のみがレデューサーに到達します。new Text(x+" "+id)両方のマップ出力から共通のシンボル viz を持つレコードを同じレデューサーにグループ化する必要があります。ここで心打たれます。

助けてください!

4

1 に答える 1

1

これを行うには、次のように収まるパーティショナーが必要です。

  1. マッパーは一連のレコードをキーと値のペアとして出力します
  2. レコードごとに、キー、値、およびリデューサーの数がパーティショナーに渡されます。パーティショナーは、どのレデューサーがレコードを処理するかを決定します
  3. レコードは、それぞれのパーティション (リデューサー) に出荷されます。
  4. GroupingComparator は、reducer() メソッドへの 1 回の呼び出しでどのキーと値のペアを iterable にグループ化するかを決定するために実行されます。
  5. 等々...

デフォルトのパーティショナーは、キーの値全体に基づいて各レコードのレデューサー パーティションを選択していると思います (これがデフォルトの動作です)。ただし、レコードをキーの一部のみ (シンボルとタイムスタンプではなく、シンボルのみ) でグループ化する必要があります。したがって、これを行うパーティショナーを作成し、ドライバー クラスで指定/構成する必要があります。

これを行うと、コンパレーターをグループ化すると、意図したとおりにレコードをグループ化するのに役立ちます。

編集:ランダムな考え

  • タイムスタンプを値に移動して、キーを単純 (シンボルのみ) にし、値を複雑 (タイムスタンプと値) にすると、作業が簡単になる場合があります。そうすれば、パーティショナーやグループ化コンパレーターは必要ありません。
  • どちらとも言えませんが、MultipleInputs クラスを使用していましたね。これが、同じジョブに対して 2 つ以上のマッパーを呼び出す唯一の方法です。
于 2012-11-04T21:46:44.157 に答える