mysql - 如何防止多个worker竞相处理同一个任务?

标签 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

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

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

最佳答案

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

In order to use optimistic locking, the table needs to have a column called lock_version of type integer. Each time the record is updated, Active Record increments the lock_version column. If an update request is made with a lower value in the lock_version field than is currently in the lock_version column in the database, the update request will fail with an ActiveRecord::StaleObjectError.

Pessimistic locking uses a locking mechanism provided by the underlying database. Using lock when building a relation obtains an exclusive lock on the selected rows. Relations using lock are usually wrapped inside a transaction for preventing deadlock conditions.

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

两者都应该有效,但每个都需要不同的实现。从你所做的来看,我会考虑悲观锁定,因为发生冲突的可能性相对较高。

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

关于mysql - 如何防止多个worker竞相处理同一个任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19012123/

相关文章:

mysql - 通过过滤器搜索在datagridview中显示多个值

ruby-on-rails - 无法自动加载常量 Api::V1::UsersController

ruby - 如何在 Rakefile 中上传 IronWorker 的工作人员?

iphone - 如何允许一个线程改变数组属性,而另一个线程迭代数组的副本

c# - 在并行任务与异步任务上使用 Task.Wait

mysql - SQL 中的最大连接数到底意味着什么?

MySQL 将数据从 5.1 迁移到 5.6 - 威胁

sql - MySQL:选择最接近的匹配项?

Ruby:删除字符串开头的空白字符

Java:简单的 If 语句不执行