如何将Resque作业锁定到一台服务器



我在基础架构中有一个Resque服务器的"群集"。他们都具有相同的确切工作优先级等。我根据有多少工作的工作以及服务器上的可用资源来自动缩放Resque服务器的数量,以处理上述工作。我总是至少有两个Resque服务器。

我的问题是,当我做快速的工作,有时两个服务器处理该作业时。这是不好的。

我尝试使用以下内容添加锁定:

require 'resque-lock-timeout'
class ExampleJob
  extend Resque::Plugins::LockTimeout
  def self.perform
   # some code
  end
end

此插件适用于更长的运行作业。但是,对于这些超级小的工作,加工就会立即进行。Resque服务器都看不到其姐妹服务器设置的锁,都设置了锁,处理作业,解锁并完成。

除了让一个专用服务器处理此类型的作业外,我不确定该怎么做或有哪些解决方案。这将是一个严重的配置和规模痛苦。我真的希望两个服务器都能处理它,但是一旦其中一个从队列中抓住它,请确保另一个不运行它。

任何人都可以建议一些可行的解决方案吗?

写下您的锁解释器以等待 T毫秒,然后再寻找一个锁定的锁,而小于锁的值

这将确定谁赢得了比赛,失败者将自我终止。

T是给定队列池中所有N服务器之间的并行延迟。您可以通过从1000毫秒的缩小缩放来确定启发式方法,直到您再次发现工作中发生的工作为止。给予延迟变化。

这被称为繁忙的等待解决方案,以使线程安全。考虑到必须解决静音的各种情况(例如锁定等)

,它被认为是可以接受的权衡之一。

我将在移动设备上发布一些链接。Mutex上的Wikipedia条目应解释这一切。

这对您不起作用,然后:1.使用调度程序控制重复。2.将短运行作业分类为旨在串行运行的队列。

tl; dr没有完美的解决方案,仅适合您的条件。

两个工人不可能获得相同的'有效载荷',因为使用 BLPOP脱水。REDIS仅将排队项目发送给第一个调用BLPOP的客户端。听起来您不止一次地吸引工作,因此两名工人能够以相同的参数获取不同的有效载荷。" Resque-lock timeout"的目的是确保具有相同方法和参数不会同时运行的有效载荷;但是,如果第一份工作在第二份工作试图获取锁之前释放锁定,则不会阻止第二个有效载荷的工作。

这只会在短期运行工作中才有意义。这是可能发生的事情:

payload 1 is enqueued
payload 2 is enqueued
payload 1 is locked 
payload 1 is worked
payload 1 is unlocked
payload 2 is locked
payload 2 is worked
payload 2 is unlocked

与长期运行的工作一样,以下senario可能发生:

payload 1 is enqueued
payload 2 is enqueued
payload 1 is locked
payload 1 is worked 
payload 2 is fails to get lock
payload 1 is unlocked

尝试关闭Resque并吸引您的工作。查看redis的列表中的resque队列(或使用redis-cli monitor进行监视Redis)。看看Resque是否排队多个有效载荷。如果您仍然只看到一个有效载荷,请监视列表,以查看您的另一名重用工人在失败的工作中调用recreate

如果要使'resque-lock timeout'保持锁的时间比处理工作所需的持续时间更长,则可以覆盖release_lock!方法以在锁上设置有效期,而不是删除它。

module Resque
  module Plugins
    module LockTimeout  
      def release_lock!(*args)
        lock_redis.expire(redis_lock_key(*args), 60) # expire lock after 60 seconds
      end
    end
  end
end

https://github.com/lantins/resque-lock timeout/blob/master/lib/lib/resque/plugins/lock_timeout.rb#l153-155

相关内容

最新更新