我在基础架构中有一个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