如何防止多名工人参加同样的任务?

时间:2013-09-25 18:06:51

标签: mysql ruby concurrency backgroundworker

我启动这个工作者10次以给它一种并发感:

class AnalyzerWorker
  @queue = :analyzer

  def self.perform
    loop do
      # My attempt to lock pictures from other worker instances that may
      # try to analyze the same picture (race condition)

      pic = Pic.where(locked: false).first
      pic.update_attributes locked: true 

      pic.analyze
    end
  end
end

这段代码实际上仍然容易受到竞争条件的影响,我认为其中一个原因是因为获取未锁定图片与实际锁定之间存在时间差。

也许有更多的理由,任何可靠的方法来防止这种情况?

1 个答案:

答案 0 :(得分:0)

Active Record提供乐观锁定和悲观锁定。

  

为了使用optimistic锁定,表格需要有一个列   称为整数类型的lock_version。每次更新记录时   Active Record会增加lock_version列。如果有更新请求   在lock_version字段中使用比当前值更低的值   在数据库的lock_version列中,更新请求将会   使用ActiveRecord :: StaleObjectError失败。

     

Pessimistic锁定使用由...提供的锁定机制   底层数据库。在建立关系时使用锁获得   对所选行的独占锁定。通常使用锁定的关系   包含在事务中以防止死锁条件。

代码示例在引用的链接中提供......

要么应该工作,但每个都需要不同的实现。从你的工作开始,我会考虑悲观锁定,因为冲突的可能性相对较高。

然而,正如您所指出的那样,您当前的实现是两者的混合,它确实无法解决问题。您可能能够使用它,但使用Active Record实现是有意义的。