1

カスタム パーティショナーの「getPartition」メソッドの出力に基づいて、予想されるパーティションにカスタム中間キーが配置されないという問題が発生しています。私のマッパー ログ ファイルで、パーティショナーが予想されるパーティション番号を生成することを確認できますが、共通のパーティション番号を持つキーが同じリデューサーにならないことがあります。

共通の「getPartition」出力を持つキーは、どのようにして異なるレデューサーに到達しますか?

すべての「getPartition」呼び出しが行われた後、マッパー ログ ファイルで、カスタム中間キー「hashCode」および「compareTo」メソッドへの呼び出しが多数行われていることに気付きました。マッパーはパーティションの並べ替えを行っているだけですか、それとも問題の一部である可能性がありますか?

カスタム中間キーとパーティショナーのコードを添付しました。注: キーの正確に 1/2 で「useBothGUIDFlag」が true に設定され、1/2 でこれが false に設定されていることがわかっています (これが、これらのキーをパーティション スペースの半分に分割する理由です)。また、キーがパーティションの残りの半分にクロスオーバーしていないように見えることも知っています (つまり、「useBothGUIDFlag」キーは「!useBothGUIDFlag」パーティションに到達せず、その逆も同様です)。パーティション。

public class IntermediaryKey implements WritableComparable<IntermediaryKey> {

    public String guid1;
    public String guid2;
    public boolean useBothGUIDFlag;

    @Override
    public int compareTo(IntermediaryKey other) {
        if(useBothGUIDFlag)
        {
            if(other.useBothGUIDFlag)
            {
                return this.hashCode() - other.hashCode();
            }else{
                return 1;
            }
        }else{
            if(!other.useBothGUIDFlag)
            {
                return guid2.compareTo(other.guid2);
            }else{
                return -1;
            }
        }
    }

    @Override
    public int hashCode()
    {
        if(useBothGUIDFlag)
        {
            if(guid1.compareTo(guid2) > 0)
            {
                return (guid2+guid1).hashCode();
            }else{
                return (guid1+guid2).hashCode();
            }
        }else{
            return guid2.hashCode();
        }
    }

    @Override
    public boolean equals(Object otherKey)
    {
        if(otherKey instanceof IntermediaryKey)
        {
            return this.compareTo((IntermediaryKey)otherKey) == 0;
        }
        return false;
    }
}

public static class KeyPartitioner extends Partitioner<IntermediaryKey, PathValue>
{
    @Override
    public int getPartition(IntermediaryKey key, PathValue value, int numReduceTasks) {
        int bothGUIDReducers = numReduceTasks/2;
        if(bothGUIDReducers == 0)
        {
            return 0;
        }

        int keyHashCode = Math.abs(key.hashCode());
        if(key.useBothGUIDFlag)
        {
            return keyHashCode % bothGUIDReducers;
        }else{
            return (bothGUIDReducers + (keyHashCode % (numReduceTasks-bothGUIDReducers)));
        }
    }
}
4

1 に答える 1

0

問題は、カスタムキー(IntermediaryKey)のシリアル化/逆シリアル化にあることになりました。「useBothGUIDFlag」変数は、本来あるべきものとは逆に読み込まれていました。

レデューサー内で「mapred.task.partition」プロパティ値を取得すると、このスワップが発生したことに気付くのに役立ちました。反対の「useBothGUIDFlag」値を持つキーは、正しいレデューサーに送られているように見えました。

于 2012-10-30T17:33:14.580 に答える