【问题标题】:How to prevent multiple workers from racing to process the same task?如何防止多个工人竞相处理同一任务?
【发布时间】:2013-09-25 18:06:51
【问题描述】:

我启动这个worker 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

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

也许还有更多原因,有什么可靠的方法可以防止这种情况发生吗?

【问题讨论】:

    标签: mysql ruby concurrency backgroundworker


    【解决方案1】:

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

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

    Pessimistic 锁定使用由 底层数据库。在建立关系时使用锁获得一个 对选定行的排他锁。使用锁的关系通常是 包裹在事务中以防止死锁情况。

    参考链接中提供了代码示例...

    两者都应该工作,但每个都需要不同的实现。根据您的操作,我会考虑悲观锁定,因为发生冲突的可能性相对较高。

    您当前的实现是两者的混合,但是,正如您所指出的,它确实不能解决问题。你也许可以让你的工作,但使用 Active Record 实现是有意义的。

    【讨论】:

    • 有什么进展吗?这有帮助吗?我还能做什么?
    • 这解决了您的问题吗?如果没有,您有问题吗?如果是,你能接受吗?谢谢...
    猜你喜欢
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 2016-12-09
    • 1970-01-01
    • 2016-08-29
    • 1970-01-01
    相关资源
    最近更新 更多