2012-04-07 1 views
5

내 응용 프로그램은 사용자별로 순차적으로 처리해야하는 resque 작업을 생성하며 최대한 빨리 처리해야합니다 (최대 지연 1 초).Resque : 사용자별로 순차적으로 실행되는 시간이 중요한 작업

예 : 사용자 1에게는 job1과 job2가 작성되고 사용자 2에게는 job3이 작성됩니다. Resque는 job1과 job3을 병렬로 처리 할 수 ​​있지만 job1과 job2는 순차적으로 처리해야합니다.

가 나는 해결책에 대해 서로 다른 생각을 가지고

  • 내가 다른 대기열을 사용할 수 있습니다 (예를 들어, queue_1 ... queue_10)를 각각의 큐 (예를 들어, rake resque:work QUEUE=queue_1)에 대한 작업자를 시작합니다. 사용자는 런타임에 대기열/작업자에게 할당됩니다 (예 : 로그인, 매일 등)
  • 동적 "사용자 대기열"(예 : queue _ # {user.id})을 사용하여 1 명의 작업자 (Resque: one worker per queue에서 묻는대로)
  • 대기열이 아닌 대기열에 작업을 넣고 이러한 작업을 처리하는 resque-lock (https://github.com/defunkt/resque-lock)과 함께 "사용자 별 메타 작업"을 사용할 수 있습니다.

실습 중 하나와 관련된 경험이 있습니까? 아니면 생각할 가치가있는 다른 아이디어가 있습니까? 나는 어떤 의견을 주셔서 감사합니다, 감사합니다!

답변

5

덕분에 (레디 스에서 resque 다시 시도하고 잠금을 사용하여 :

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 (http://redis.io/commands/setex의 패턴을 캡슐화 함)

2

이전에 해 보았습니다.

이와 같은 작업을 순차적으로 수행하는 가장 좋은 해결책은 job1의 끝을 job2에 대기시키는 것입니다. job1과 job2는 동일한 큐 또는 다른 큐에 들어갈 수 있습니다. 순차적으로 중요하지는 않습니다. 여러분에게 달려 있습니다.

동시에 job1 + 2를 대기열에 넣는 것과 같은 다른 해결책이지만 job2에 0.5 초 이내에 시작하도록 알려주면 경쟁 조건이 발생하므로 권장하지 않습니다.

job1 트리거 작업 2를 갖는 것도 매우 쉽습니다.

또 다른 옵션을 원한다면 두 번째 작업을 단일 작업으로 묶고 두 번째 부분도 트리거해야하는 경우 param을 추가하는 것이 좋습니다.

내가 마지막으로 작동하는 것 같다 솔루션에 온 @Isotope의 대답

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