5

私のアプリケーションは、ユーザーごとに順次処理する必要がある resque ジョブを作成し、できるだけ速く処理する必要があります (最大 1 秒の遅延)。

例: user1 には job1 と job2 が作成され、user2 には job3 が作成されます。Resque は job1 と job3 を並行して処理できますが、job1 と job2 は順番に処理する必要があります。

私は解決策についてさまざまな考えを持っています:

  • 異なるキュー (例: queue_1 ... queue_10) を使用して、各キュー (例: rake resque:work QUEUE=queue_1) のワーカーを開始できます。ユーザーは実行時にキュー/ワーカーに割り当てられます (ログイン時、毎日など)。
  • 動的な「ユーザー キュー」(例: queue_#{user.id}) を使用して、一度に 1 つのワーカーだけがキューを処理できるように resque を拡張しようとすることができます ( Resque: one worker per queueで質問されているように) 。
  • ジョブを非レスキュー キューに入れ、それらのジョブを処理するレスキュー ロック ( https://github.com/defunkt/resque-lock ) を備えた「ユーザーごとのメタ ジョブ」を使用できます。

これらのシナリオのいずれかを実際に使用した経験はありますか? または、検討する価値のある他のアイデアはありますか? ご意見をいただければ幸いです。ありがとうございます。

4

2 に答える 2

5

@Isotope の回答のおかげで、私は最終的にうまくいくように見える解決策にたどり着きました ( resque-retry と redis のロックを使用します:

class MyJob
  extend Resque::Plugins::Retry

  # directly enqueue job when lock occurred
  @retry_delay = 0 
  # we don't need the limit because sometimes the lock should be cleared
  @retry_limit = 10000 
  # just catch lock timeouts
  @retry_exceptions = [Redis::Lock::LockTimeout]

  def self.perform(user_id, ...)
    # Lock the job for given user. 
    # If there is already another job for the user in progress, 
    # Redis::Lock::LockTimeout is raised and the job is requeued.
    Redis::Lock.new("my_job.user##{user_id}", 
      :expiration => 1, 
      # We don't want to wait for the lock, just requeue the job as fast as possible
      :timeout => 0.1
    ).lock do
      # do your stuff here ...
    end
  end
end

私はここでhttps://github.com/nateware/redis-objectsの Redis::Lock を使用しています ( http://redis.io/commands/setexのパターンをカプセル化しています)。

于 2012-06-07T14:16:23.477 に答える
2

私は前にこれをやったことがあります。

このようなことを確実にするための最善の解決策は、ジョブ 1 の最後にジョブ 2 をキューに入れることです。その後、job1 と job2 は同じキューまたは異なるキューのいずれかに入ることができます。順番は関係ありません。それはあなた次第です。

ジョブ 1 と 2 を同時にキューに入れるなど、その他の解決策はありますが、ジョブ 2 に 0.5 秒で開始するように指示すると、競合状態が発生するため、お勧めできません。

job1 で job2 をトリガーすることも非常に簡単です。

そのために別のオプションが必要な場合: 私の最後の提案は、両方のジョブを 1 つのジョブにバンドルし、2 番目の部分もトリガーする必要がある場合にパラメーターを追加することです。

例えば

def my_job(id, etc, etc, do_job_two = false)
  ...job_1 stuff...
  if do_job_two
    ...job_2 stuff...
  end
end
于 2012-04-11T09:12:12.667 に答える