複数のワーカーが Redis 経由でプールを共有する場合、ソート済みセットで単純な方針を実装できます。記録された割り当てが最も少ない対象プロキシを選ぶのです。プロキシ識別子をメンバー、割り当て回数をスコアとして保存します。

許可された公開リクエストを処理するプールでは、無料プロキシ一覧からエンドポイント候補を取得し、そのプールの適格性ルールで評価できます。対象メンバーは合意した初期値で初期化します。次に選択と加算を 1 つのサーバー側操作にします。

local chosen = redis.call('ZRANGE', KEYS[1], 0, 0)[1]
if not chosen then
    return nil
end

redis.call('ZINCRBY', KEYS[1], 1, chosen)
return chosen

ソート済みセットのキーを、Redis クライアントの EVAL インターフェースでスクリプトの唯一のキー引数として渡します。空のプールは null を返すため、アプリケーションはリクエストを送らずに処理する必要があります。

なぜ 2 つのコマンドをまとめるのか

読み取りと加算が分かれていると、2 つのワーカーがどちらも更新する前に同じ最小値を観測できます。Redis は Lua スクリプトをアトミックに実行するため、他のワーカーがこのスクリプトの読み取りと加算の間に選択を挟むことはできません。実行中は他の Redis 処理を妨げるので、スクリプトは短く保ちます。

ZRANGE は最小のスコアを先に返します。同点はランダムではなくメンバーの順序で解決されます。ZINCRBY は選ばれたメンバーのスコアを次の割り当てのために 1 増やします。

スコアの意味を定義する

これは割り当て回数を数えるもので、後でネットワーク要求が失敗する割り当ても含みます。遅延や成功した要求、現在進行中の作業を測るものではありません。唯一の対象メンバーが繰り返し選ばれることもあり、スクリプトはそれを排他的に予約しません。

プールの健全性とポリシーのルールで適格性を維持します。メンバーを削除して後で復元する場合、過去の回数を保持するかを決めます。復元したプロキシをゼロから始めると、追いつく間そのプロキシに割り当てが集中することがあります。

最小同時実行の方針には、完了や放棄された作業の処理を含む別のライフサイクルが必要です。この累積カウンターをそのライフサイクルと解釈しないでください。

関連記事