【问题标题】:Ruby: Right way to do optimistic locking?Ruby:进行乐观锁定的正确方法?
【发布时间】:2018-10-06 19:02:53
【问题描述】:

上下文:产品正在被多个线程更新。所以它领先于比赛条件。所以我使用乐观锁定,因为它经常不更新。产品的最新更新状态由updated_at属性决定。

例如,Prod (id=1) 在机器 t1 上更新:1。同一产品(id=1)在机器上的 t2 更新:2。现在机器上的 Prod (id=1) 状态:1 是陈旧的。

方法确定陈旧:我将机器上updated_at的值与数据库值中updated_at的存储值进行比较。

我主要关心的是设置@original_updated_at 的值。我应该使用attr_writer :original_updated_at。这是做乐观锁定的正确方法吗?

attr_accessor : :original_updated_at
  def original_updated_at
    @original_updated_at || updated_at.to_f
  end


  def stale_object?
    if updated_at.to_f > original_updated_at.to_f
      @original_updated_at = nil
      return true
    else
      @original_updated_at = updated_at.to_f
      return false
    end
  end

  def recalculate
    tries = 0
    begin
      raise Product::StaleObjectError.new("StaleObjectError") if stale_object?
      attributes["updated_at"] = Time.now.utc
      Product.where(:id => self.id).update_all(attributes)
      self.attributes = attributes
    rescue Product::StaleObjectError => e
      if tries < MAX_RETRIES
        tries += 1
        sleep(1 + tries)
        reload
        retry
      else
        raise Product::StaleObjectError("StaleObjectError")
      end
    end
  end

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-4 locking


    【解决方案1】:

    看起来您正在使用 Rails?不知道您为什么要尝试推出自己的解决方案。 只需添加 lock_version 列即可在 DB 级别启用乐观锁定。

    https://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html

    另外:由于您在谈论多台机器,并发性也可能来自多个进程和多个线程。

    由于您的旧系统在添加锁定列时会中断一些其他解决方案:

    1. 修复乐观锁定问题

    2. 使用悲观锁定。根据负载情况 - 并发读/写的数量 - 这可能也可以工作

    3. 修复你的锁定代码(不完全确定它是如何工作的,因为你遗漏了相关类的一些细节)

    • 无需加注、捕捉和重新加注(只需使用循环并break成功)
    • 你在浮动上调用to_f
    • 我不知道self.attributes = attributes 应该做什么(从您显示的代码中不清楚attributes 是否不是self.attributes
    • 使用时间戳可能会或可能不足以确定并发更新(可能会生成两个完全相同的时间戳,多台机器上的时钟可能会关闭,时钟可能会在两者之间重置或调整)
    • 使用sleep 是一种代码味道

    当您编写的代码如此复杂以至于您不得不在互联网上询问它是否有效时,那么您可能走错了路。修复乐观锁定的问题,而不是添加这样的解决方法。

    【讨论】:

    • 由于某种原因lock_version 无法正常工作。所以不能用了
    • 由于什么原因?我建议您解决阻止您使用久经考验的解决方案而不是尝试推出自己的解决方案的问题。或者描述导致你自己滚动的约束......
    • 这个遗留系统。当我使用“lock_version”时,多个现有测试用例失败,我不想在模型中添加额外的列。您能否提出当前解决方案不可行的原因。
    猜你喜欢
    • 2016-09-23
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多