6

我的基础架构中有一个 Resque 服务器“集群”。它们都具有完全相同的作业优先级等。我会根据有多少待处理的作业以及服务器上用于处理所述作业的可用资源来自动上下缩放 Resque 服务器的数量。我总是至少有两个 Resque 服务器。

我的问题是,当我完成一项快速的临时工作时,有时两个服务器都会处理该工作。这是不好的。

我尝试使用以下内容为我的工作添加锁:

require 'resque-lock-timeout'

class ExampleJob
  extend Resque::Plugins::LockTimeout

  def self.perform
   # some code
  end
end

该插件适用于运行时间较长的作业。然而,对于这些超小的一次性工作,处理会立即发生。Resque 服务器都看不到其姊妹服务器设置的锁,都设置了锁,处理作业,解锁并完成。

除了让一台专用服务器处理此类工作之外,我不完全确定此时该做什么或有什么解决方案。配置和扩展这将是一个严重的痛苦。我真的希望两台服务器都能够处理它,但是一旦其中一台从队列中抓取它,请确保另一台不运行它。

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

4

2 回答 2

2

编写你的锁解释器等待T几毫秒,然后它会寻找一个 unique_id小于它所创建的锁的值的锁

这将决定谁赢得比赛,而失败者将自行终止。

TN是给定队列池中所有服务器之间的并行延迟。您可以通过从 1000 毫秒缩减直到您再次发现重复发生的工作来启发式地确定这一点。为延迟变化提供填充。

这称为互斥线程安全的 Busy-Wait 解决方案。考虑到必须解决互斥锁的各种场景(例如锁定等),它被认为是可接受的权衡之一

我会在关闭移动设备时发布一些链接。互斥量的维基百科条目应该解释这一切。

那么这对您不起作用: 1. 使用调度程序来控制复制。2. 将短期运行的作业分类到一个设计用来串行运行它们的队列中。

TL;DR 没有完美的解决方案,只有根据您的条件进行良好的权衡。

于 2012-10-28T06:16:33.203 回答
1

两个工作人员应该不可能获得相同的“有效负载”,因为项目是使用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

在长时间运行的作业中,可能会发生以下情况:

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 并将您的工作排入队列。查看 Resque 队列列表中的 redis(或使用 监视 Redis redis-cli monitor)。查看 Resque 是否已将多个有效负载排队。如果您仍然只看到一个有效负载,则监视该列表以查看您的另一位 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/resque/plugins/lock_timeout.rb#l153-155

于 2012-10-30T17:07:42.560 回答