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

ran*_*its 6 ruby ruby-on-rails resque redis

我的基础架构中有一个Resque服务器的"集群".它们都具有相同的确切工作优先级等.我根据有多少待处理作业以及服务器上用于处理所述作业的可用资源,自动扩展Resque服务器的数量.我总是至少有两个Resque服务器.

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

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

require 'resque-lock-timeout'

class ExampleJob
  extend Resque::Plugins::LockTimeout

  def self.perform
   # some code
  end
end
Run Code Online (Sandbox Code Playgroud)

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

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

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

New*_*ria 2

T编写锁解释器,使其在查找 unique_id小于它所创建的锁的值的锁之前等待几毫秒。

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

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

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

关闭手机时我会发布一些链接。维基百科关于互斥体的条目应该解释这一切。

这对你来说不起作用,那么: 1. 使用调度程序来控制重复。2. 将短期运行的作业分类到旨在串行运行它们的队列中。

TL;DR 没有完美的解决方案,只有适合您的条件的良好权衡。

  • Resque 使用 Redis 的原子列表操作,这完全避免了锁定的需要,以避免重复作业处理,因为可以保证只有一个客户端能够从列表中弹出一项。这个答案与技术无关。 (2认同)