2012-04-07 10 views
5

私のアプリケーションでは、ユーザーごとに順次処理する必要があるresqueジョブが作成され、できるだけ早く処理する必要があります(1秒の最大遅延)。Resque:ユーザーごとに順次実行されるタイムクリティカルなジョブ

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

は、私は解決策のためのさまざまな考えがあります。

  • 私は別のキューを使用することができます(例えばqueue_1 ... queue_10)を、各キュー(例えばrake resque:work QUEUE=queue_1)のために労働者を起動します。
  • 動的な「ユーザーキュー」(例:queue _#{user.id})を使用してresqueを拡張しようとすると、1人の作業者しか実行できません(Resque: one worker per queueで質問)
  • 私はジョブを非再キューに入れ、それらのジョブを処理するresque-lock(https://github.com/defunkt/resque-lock)を持つ "ユーザごとのメタジョ​​ブ"を使用することができました。

これらのシナリオのいずれかについて実際に経験がありますか?それとも、考えてみる価値のある他のアイデアがありますか?私はどんな入力にも感謝します、ありがとう!

答えて

5

私は最終的にRedisの中resqueリトライやロックを使用して(動作するようです解決策に来た@Isotopeの答えのおかげ:私はここの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 

は:: Lockからhttps://github.com/nateware/redis-objects(それはhttp://redis.io/commands/setexからパターンをカプセル化します)。

2

私は以前これを行っています。

このようなことを順番に確認する最良の解決策は、job1の最後にjob2をキューに入れることです。 job1とjob2は、同じキューまたは異なるキューに入ることができます。順番に関係なく、あなた次第です。

同時にジョブ2をキューに入れるなどの他の解決方法では、ジョブ2を0.5秒で開始するように指示すると競合状態になるため、お勧めしません。

job1トリガーjob2を持つことも、本当に簡単です。

もう1つのオプションが必要な場合:最後に、両方のジョブを1つのジョブにバンドルし、2番目の部分をトリガーする場合のパラメータを追加することをお勧めします。

def my_job(id, etc, etc, do_job_two = false) 
    ...job_1 stuff... 
    if do_job_two 
    ...job_2 stuff... 
    end 
end 
+0

問題は、彼らはそれらが同時に作成されていないので、job1が明示的に(それらが異なる要求などで作成された可能性がある)JOB2について知るべきではないということである。場合 – lacco

+0

私はjob2上でresque-retryを使うだろうが、 job1が終了し、後で再キューしない場合にチェックを実行する - resque-retryは、必要に応じて指数バックオフまたは制限付き試行を使用するように設定できます。 – TomDunning

+0

job2は、特定のユーザーのjob1が進行中であることをどのように認識していますか? – lacco

関連する問題