1

答えが一般的な設計パターンにあると思われるため、データベースの詳細なしでこの質問をしています。システム固有のソリューションは必ずしも必要ではありません (私の特定のシステム設定は質問の最後で参照されています)。

ID、URL、および処理フィールドを含む会社のデータベースを取得して、その会社が現在私のクローラーの 1 つによって処理されているかどうかを示します。多くのクローラーを並行して実行します。それぞれが処理する会社を選択し、その会社を処理開始前に設定して、各会社が常に 1 つのクローラーによってのみ処理されるようにする必要があります。

どの企業が処理されているかを追跡するには、システムをどのように構築すればよいですか?

ここでの課題は、データベースで処理されていない会社を検索し、その会社を更新して処理済みとして設定することができないことです。その間に別のクローラーがその会社を選択した可能性があるからです。これは、データを並列処理するときによくある問題のように思えるので、理論上のベスト プラクティスを探しています。

これには MySQL を使用していましたが、プロセッサ間の一貫性を維持するために次のコードを使用しました。しかし、私はシステムを再設計しており、ElasticSearch がメインのデータベースおよび検索サーバーになる予定です。以下の MySQL ソリューションは、常にハックのように感じられ、この並列化の問題に対する適切なソリューションではありませんでした。

public function select_next()
{

    // set a temp variable that allows us to retrieve id of the row that is updated during next query
    $sql = 'SET @update_id := 0';
    $Result = $this->Mysqli->query( $sql );
    if( ! $Result )
        die( "\n\n    " . $this->Mysqli->error . "\n" . $sql );

    // selects next company to be crawled, marks as crawling in the db
    $sql = "UPDATE companies
            SET
                crawling = 1,
                id = ( SELECT @update_id := id )
            WHERE crawling = 0
            ORDER BY last_crawled ASC, id ASC
            LIMIT 1";
    $Result = $this->Mysqli->query( $sql );
    if( ! $Result )
        die( "\n\n    " . $this->Mysqli->error . "\n" . $sql );

    // this query returned at least one result and there are companies to be crawled
    if( $this->Mysqli->affected_rows > 0 )
    {

        // gets the id of the row that was just updated in the previous query
        $sql = 'SELECT @update_id AS id';
        $Result = $this->Mysqli->query( $sql );
        if( ! $Result )
            die( "\n\n    " . $this->Mysqli->error . "\n" . $sql );

        // set company id
        $this->id = $Result->fetch_object()->id;

    }

}
4

1 に答える 1

1

このような問題によく使用されるアプローチの 1 つがシャーディングです。データベース内の各行をクローラーに割り当てる決定論的関数を定義できます。あなたの場合、そのような関数は単に企業IDモジュロ数のクローラーにすることができます。各クローラーは、このワーカー シャードに属する会社を順次処理できます。これにより、会社が同時に処理されることはありません。

このようなアプローチは、たとえばMapReduceの Reduce 部分で使用されます。

利点は、実装が難しく、特に分散環境でしばしばボトルネックとなるトランザクションやロックが必要ないことです。欠点は、作業がクローラー間で均等に分割されない可能性があることです。この場合、他のクローラーがまだ処理中であるときに、一部のクローラーがアイドル状態になります。

于 2012-11-27T22:09:16.570 に答える